Tuesday, December 23, 2014

Trust your auto indentation... really

I knew I liked my editor's autoindent feature, but I didn't realize how valuable it was until this situation popped up. I was reading the book Rebuilding Rails (worth a look) and happened to code a simple method as part of one example.
def call(env)
  (klass, act) = get_controller_and_action(env)
       controller = klass.new(env)
       text = controller.send(act)
  [200, {"Content-Type" => "text/html"},
As you can see the indentation isn't correct for the 'controller =' and 'text =' lines and try as I might
vim gg=G
it wouldn't indent properly.  I chalked it up as low priority weirdness to be dealt with later until I loaded up the program and got this error:

undefined local variable or method `controller' for ...

I finally dropped into HexDump mode using vim's nifty little xxd utility
and got this output for the lines that wouldn't indent properly.
0000060: 6c28 656e 7629 0a20 2020 2020 2028 6b6c  l(env).      (kl
0000070: 6173 732c 2061 6374 2920 3d20 6765 745f  ass, act) = get_
0000080: 636f 6e74 726f 6c6c 6572 5f61 6e64 5f61  controller_and_a
0000090: 6374 696f 6e28 656e 7629 0a20 2020 2020  ction(env).    
00000a0: 20c2 a0c2 a0c2 a0c2 a0c2 a063 6f6e 7472   ..........contr
00000b0: 6f6c 6c65 7220 3d20 6b6c 6173 732e 6e65  oller = klass.ne
00000c0: 7728 656e 7629 0a20 2020 2020 20c2 a0c2  w(env).      ...
00000d0: a0c2 a0c2 a0c2 a074 6578 7420 3d20 636f  .......text = co
00000e0: 6e74 726f 6c6c 6572 2e73 656e 6428 6163  ntroller.send(ac
Notice the 'c2a0' sequence repeated five times in front of the 'controller =' and 'text =' lines. Those non-printing characters were the culprit: the actual variable name was 0x'c2a0c2a0c2a0c2a0c2a0'controller, for example so when I tried to use 'controller', that was still undefined. How those byte pairs got inserted remains a mystery. But I am guessing from this post that it was a non-breaking Unicode character.