Open a bash command in your text editor

Thanks to this vim lighting talk I’ve just discover pressing ctrl+x, ctrl+e on bash opens your favorite text editor with the command you are typing. After saving and closing your editor the command is executed on bash.

Good when a command starts to be too long.

How could I live without knowing that?

Useful mapping to write some Spanish words in Vim

Usually I write on an UK keyboard and just change the keyboard layout when I need to type some Spanish text. This is easy and handy, just pressing alt + shift I’m able to change the layout.

Recently I’ve started to help with the translation of Perl Maven Tutorial to Spanish. Problem here is that code and Spanish text is mixed so I have to switch the layout constantly and turns out to be a nightmare. I could just type using Spanish keyboard layout but coding in general becomes tougher and Vim commands in particular become hell. (How was I able to do this for so many years?)

So I came across with some simple mappings that allow me to write most Spanish words I might need keeping the UK keyboard layout:

function! SpanishMap()
  if (g:spanishMap)
    iunmap 'a| iunmap 'e| iunmap 'i| iunmap 'o| iunmap 'u
    iunmap ;a| iunmap ;e| iunmap ;i| iunmap ;o| iunmap ;u
    inoremap 'a á| inoremap 'e é| inoremap 'i í| inoremap 'o ó| inoremap 'u ú
    inoremap ;a ña| inoremap ;e ñe| inoremap ;i ñi| inoremap ;o ño| inoremap ;u ñu
  let g:spanishMap = !g:spanishMap
let g:spanishMap = 0
call SpanishMap()
noremap <C-F12> :call SpanishMap()<CR>

So now I can type words in the same way I would do on a Spanish keyboard. Writing something like:

Con estas razones perd‘ia el pobre caballero el juicio, y desvel‘abase por entenderlas y desentra;arles el sentido,

I’ll get:

Con estas razones perdía el pobre caballero el juicio, y desvelábase por entenderlas y desentrañarles el sentido,

A minor bug that appears, if I try to quote something like ‘a wrong quote’ I’ll get something like á wrong quote’.

I can still use double quotes or disable it temporarily by using ctrl + F12, so it is good enough to me :)

Pedal for Vim

Awesome idea:

VIM Clutch is a hardware pedal for improved text editing speed for users of the magnificent VIM text editor (1, 2). When the pedal is pressed down, the pedal types “i” causing VIM to go into Insert Mode. When released, it types and you are back in Normal Mode.

VIM Clutch by Aleksandr Levchuk


Pong Games!

I’m doing the interesting course An Introduction to Interactive Programming in Python, weekly we have to present some mini project consisting on simple games.

One I really like is the Pong game, so I developed some extensions to the game. The result is MultiPong:
Multi Pong
Which is a madness game with several balls that can collide an have gravity, hardly playable but I had some fun doing it.

Some classmates did amazing things, so here are some of the ones I like.

Tweaking command-not-found to get quick access to tickets

Whenever someone send me a ticket number I have to do several steps:

  1. Alt+Tab to find Firefox
  2. Ctrl+T to get a new tab
  3. Type the Firefox keyword for the ticket system (I have “t” for trac)
  4. Search the ticket number

I don’t have many tickets because my code never fails (:D), but anyway it is quite boring to do all that.

So why not just press ALT+F2 and introduce the ticket number.
Turn out to be quite easy, I just modified the command-not-found script:

vi `which command-not-found`

and replace the line:

cnf = CommandNotFound(options.data_dir)


from subprocess import call
import numbers
if args[0].isdigit():
    call(["firefox", "-new-tab", "http://company.trac.url/ticket/" + args[0]])
    cnf = CommandNotFound(options.data_dir)

This just opens a new tab in Firefox with the ticket I type as a command.
This works on Firefox and Trac, but should be almost the same on any other browser or ticket system.

Now my productivity is boost ;-)

Finished some R courses

I’ve just passed the Try R and Computing for Data Analysis courses.

x_smile <- seq(-0.75, 0.75, 0.01)
y_smile <- x_smile ^ 2
x_eyes  <- c(-0.5, 0.5)
y_eyes  <- c(1.5, 1.5)
x <- c(x_smile, x_eyes)
y <- c(y_smile, y_eyes)
plot(x,y, xlim = c(-1.0, 1.0), ylim = c(-0.25, 1.75))

R Smile
I also finished Try Ruby recently and now I’m looking at Rails for Zombies Redux, which is the better course ever.

So many free courses are going to destroy my health :-/

Playing with a Perl proxy. Part 1: Kitties everywhere

I’ve spent recently some time playing with the Perl module HTTP::Proxy which allows to create a proxy in a few lines of code. One interesting thing is that makes possible on live modifications of the content.

As the documentation of HTTP::Proxy::BodyFilter::simple states, we can do something like:

my $filter = HTTP::Proxy::BodyFilter::simple->new(
    sub { ${ $_[1] } =~ s/foo/bar/g; }

and that will replace all ‘foo’ strings by ‘bar’.

So I proposed myself to create a proxy that replace all images by kitties, because kitties are the best of the Internet. With the magic of HTTP::Proxy and placekitten we can write something like:

use strict;
use warnings;
use HTTP::Proxy;
use HTTP::Proxy::BodyFilter::simple;

# Create proxy
my $proxy  = HTTP::Proxy->new(in => { port => 8080 });
my $filter = HTTP::Proxy::BodyFilter::simple->new(\&tamper_image);
$proxy->push_filter(mime => 'text/html', response => $filter);

# Modify images
sub tamper_image {
  my ( $self, $dataref, $message, $protocol, $buffer ) = @_;

  my @matches = ($$dataref =~ m#(<img.*?src[\s|\t]*=["|'].*?["|'].*/?>)#g);
  foreach my $match (@matches) {
    $match =~ m#width[\s|\t]*=["'](.*?)["']#;
    my $width  = $1;
    $match =~ m#height[\s|\t]*=["'](.*?)["']#;
    my $height = $1;

    if ($width && $height) {
      $$dataref =~ s#$match#<img alt="" src="$width/$height" />#;

This code creates a proxy on the port 8080 and assings a filter to all html files. This filter will search for all img tags and will replace the source of the image.
If we run this script and configure our web browser to use a proxy on localhost:8080 we will start to see cats instead of some pictures.
Replacement of images by cats

Isn’t that great?

Well, it has some problems. To begin with I used a regex to parse the html instead of some module dedicated to it, so this code is messing around with the html and breaking some things. Nevertheless of that it will only alter the images with width and height properties defined. If the dimensions or the image are defined in css, javascript or other madness there is no simple way to know the appropriate size to get the right cat.

Because of this flaws I’ve tried another approach: tamper the image data itself and keep untouch the html code.

use strict;
use warnings;
use HTTP::Proxy;
use HTTP::Proxy::BodyFilter::simple;
use Imager;
use LWP::Simple qw($ua get);
# Some cats want an appropriate user agent
$ua->agent('Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0');

my($type, $port) = @ARGV;
$type ||= "cats";
$port ||= 8080;

# There are more things that cats on the Internet
  cats   => '',
  dogs   => '',
  apes   => '',
  random => '',
  puppy  => '',
  sheen  => '',
$PLACE_HOLDERS{$type} || die "I don't know how to replace that: $type";

# Create proxy
my $proxy  = HTTP::Proxy->new(in => { port => $port });
my $filter = HTTP::Proxy::BodyFilter::simple->new(\&tamper_image);
$proxy->push_filter(mime => 'image/*', response => $filter);

# Modify images
sub tamper_image {
  my ( $self, $dataref, $message, $protocol, $buffer ) = @_;

  eval {
    # Get original image data
    my $img = Imager->new(data => $$dataref);
    my ($w, $h) = ($img->getwidth(), $img->getheight());

    # Construct url
    my $url = $PLACE_HOLDERS{$type};
    $url =~ s#WIDTH#$w#;
    $url =~ s#HEIGHT#$h#;

    # Get image
    $$dataref = get($url);
  if ($@) {
    $$dataref = '';

This works similar way but it applies a filter to all images and just change the image data for a different one. Besides, there are more things than cats. You can use something like apes to get:
Replaced images by apes

Extra ball

I’ve uploaded the code to GitHub and created a video tutorial:

Improving feedback in the console

Seems that managers are not like used to be, so if you miss a more classical motivation you can turn on sudo insults.

The only thing you need is edit the /etc/sudoers file (using visudo!) and add the following line:

Defaults  insults

So any time we introduce a wrong password to sudo command you will get a motivational message:

david@david-sony:~$ sudo ls
[sudo] password for david:
No soap, honkie-lips.
[sudo] password for david:
Your mind just hasn't been the same since the electro-shock, has it?
[sudo] password for david:
BOB says:  You seem to have forgotten your passwd, enter another!
sudo: 3 incorrect password attempts

It is good, but I wanted it better ;-) Why don’t have this any time I type a wrong command?
I was able to get this list of insults from the sudo source code:

Just what do you think you're doing Dave?
It can only be attributed to human error.
That's something I cannot allow to happen.
My mind is going. I can feel it.
Sorry about this, I know it's a bit silly.
Take a stress pill and think things over.
This mission is too important for me to allow you to jeopardize it.
I feel much better now.
Wrong!  You cheating scum!
And you call yourself a Rocket Scientist!
No soap, honkie-lips.
Where did you learn to type?
Are you on drugs?
My pet ferret can type better than you!
You type like i drive.
Do you think like you type?
Your mind just hasn't been the same since the electro-shock, has it?
Maybe if you used more than just two fingers...
BOB says:  You seem to have forgotten your passwd, enter another!
stty: unknown mode: doofus
I can't hear you -- I'm using the scrambler.
The more you drive -- the dumber you get.
Listen, broccoli brains, I don't have time to listen to this trash.
Listen, burrito brains, I don't have time to listen to this trash.
I've seen penguins that can type better than that.
Have you considered trying to match wits with a rutabaga?
You speak an infinite deal of nothing
You silly, twisted boy you.
He has fallen in the water!
We'll all be murdered in our beds!
You can't come in. Our tiger has got flu
I don't wish to know that.
What, what, what, what, what, what, what, what, what, what?
You can't get the wood, you know.
You'll starve!
... and it used to be so popular...
Pauses for audience applause, not a sausage
Hold it up to the light --- not a brain in sight!
Have a gorilla...
There must be cure for it!
There's a lot of it about, you know.
You do that again and see what happens...
Ying Tong Iddle I Po
Harm can come to a young lad like that!
And with that remarks folks, the case of the Crown vs yourself was proven.
Speak English you fool --- there are no subtitles in this scene.
You gotta go owwwww!
I have been called worse.
It's only your word against mine.
I think ... err ... I think ... I think I'll go home

And I copied that list in a file called /etc/insults.txt, after that I edited the file /usr/lib/command-not-found and add the following function:

def get_insult() :
        with open("/etc/insults.txt") as f:
            insults = f.readlines()

        from random import choice
        return choice(insults)
        return "I don't have words to describe you"

And adding one more line:

print(_("%s: command not found") % args[0], file=sys.stderr)

It is done. Now if type badly I will get good advices:

david@david-sony:~/Downloads$ ls-l
ls-l: command not found
Ying Tong Iddle I Po

david@david-sony:~/Downloads$ ls-l
ls-l: command not found
We'll all be murdered in our beds!

david@david-sony:~/Downloads$ ls-l
ls-l: command not found
You silly, twisted boy you.

All this is Ubuntu specific, in Debian you should install the command-not-found package and change the file /usr/bin/command-not-found.

Extra ball

sudo apt-get install cowsay

And finally changing again /usr/lib/command-not-found:

print(_("%s: command not found") % args[0], file=sys.stderr)
from subprocess import call
call(["cowsay", get_insult()])

It looks like much more better:

david@david-sony:~$ wrongcommand
wrongcommand: command not found
/ Listen, burrito brains, I don't have \
\ time to listen to this trash.        /
           (__)       )/
              ||----w |
              ||     ||

Much better apache log with some colors

When I have to debug some web application I often stared at the Apache log and say WTF!!
This is what the log might looks like:


The problem comes because every time I go into the web I get hundreds of unrelated log lines, a huge mess!

So one day I thought, could I improve that? My first idea was to add some color using grep like this:

tail -f /var/log/apache2/error.log | grep -E "ERROR|" --color


That is nicer because now I can see clearly errors in red.
Could that be better? Maybe yellow warnings?
The answer is yes, grep output can be concatenated to another grep and different colors can be used in every grep. Like this little script:

shopt -s expand_aliases

alias grey-grep="GREP_COLOR='1;30' grep -E --color=always --line-buffered"
alias red-grep="GREP_COLOR='1;31' grep -E --color=always --line-buffered"
alias green-grep="GREP_COLOR='1;32' grep -E --color=always --line-buffered"
alias yellow-grep="GREP_COLOR='1;33' grep -E --color=always --line-buffered"
alias cyan-grep="GREP_COLOR='1;36' grep -E --color=always --line-buffered"

tail -1000f /var/log/apache2/error.log | grey-grep ".*PerformanceLogger.*|$" | cyan-grep "INFO|$" | yellow-grep "WARN|$" | red-grep "[ERROR].*|[FATAL].*|$" | green-grep "***|$"

So the output looks like:


Which is really cool, errors and warnings are clearly highlighted and all the performance parts I don’t care about are in a dark gray that allows me to focus on what is going on.

Of course, real programmers don’t need colours, this is just for fun ;-)



> #!/usr/bin/perl
> use strict;
> use David;
> print David::imagination;
< Comment! >
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||