miércoles, 5 de mayo de 2010

Comparing functions. How similar are we?

Sometimes I have two functions, maybe in different subclasses, and I would like to do a diff on them, because they look very similar but not the same. Most of the times, they are come from a past copypaste, so variables have the same names.

What I want to know then is what has really changed, or if they changed at all.
#in file foo/bar.pm
sub normalize {
my ($self) = shift;
$self->attr($self->attr / $self->total);
}

#in file foo/baz.pm
sub normalize {
my ($self) = shift;
$self->attr($self->attr / $self->total +1);
}

Emacs comes to rescue!

We'll use two great emacs features, narrow and ediff.

narrow lets us hide uninteresting parts of a given buffer. It's usage is pretty simple: Mark a region, m-x narrow-to-region (or c-x n n). There's also a shorctut, and there are predefined narrowings, like narrow-to-defun... you know, emacs butterflies.

Once you narrowed two buffers to the interesting regions, you can use ediff (m-x ediff-buffers) and select the two buffers you want to narrow.

To widen the narrowed buffers, you can 'm-x widen' (or c-x n w) to see the complete buffers again.

Tip for ratpoison users (or any other tiling wm user): (setq ediff-window-setup-function 'ediff-setup-windows-plain) in your .emacs will tell emacs to open the ediff window in a different window, but not opening a new frame. (window and frame have inverse meanings in emacs world than in the rest of the world)

theese would be the steps:

  1. open bar.pm
  2. go to normalize function.
  3. c-m-h (mark-defun)
  4. c-x n n
  5. open baz.pm
  6. (steps 2-4)
  7. m-x ediff-buffers
  8. select both buffers (emacs will suggest them already)
  9. check diffs
  10. q (quit ediff-mode)
  11. c-x n w (widen)
  12. go to the other file, and widen again.
  13. You're done

Endnote: Although being a big fan of vim myself and having used it for 5 years, these features available in emacs by default, are not (at least easily) doable in vim. emacs, the kitchen sink, and m-x butterflies DO have their uses :)