Sunday, November 20, 2011

Math and Algorithm Programming with Project Euler

If you're a web developer or other type of programmer that doesn't require much math, you might be pretty weak with math based programming. Doing Project Euler problems will help to strengthen your math and algorithm programming abilities.

From the official website for Project Euler:

Project Euler is a series of challenging mathematical/computer programming problems that will require more than just mathematical insights to solve. Although mathematics will help you arrive at elegant and efficient methods, the use of a computer and programming skills will be required to solve most problems.

The way it works is you register for free on the site then it gives you problems such as "Calculate the sum of all the primes below two million." Your task is to implement an algorithm in the programming language of your choice to give you the answer. Once you have the answer, you paste it into the web site and then it tells you if you got the answer correct or not. If you answered correctly it gives you the ability to view other programmer's source code for how they did it and even submit your own if you want to.

I recommend doing some of the problems as code katas. A code kata is a way of practicing typing out low-level programming problems over and over until it becomes second nature to you--just like doing doing martial arts katas helps martial artists. I still remember some of the katas from martial arts that I haven't done in over 10 years. Repetition truly is the mother of all skill.

Another thing that doing Euler problems will help you with is learning how to optimize algorithms. The speed of the machine your program runs on will largely affect the speed of your programs, but you often don't realize it until you're doing an algorithm on some large numbers. Fortunately, many Euler problems will really push you and your machine.

You optimize the algorithms by benchmarking the program and refactoring it to run faster and faster. Sometimes you'll need to use a different math library to speed things up. For example, bcmath is a lot faster than the regular math functions in PHP for me.

How do you benchmark? The easiest way is to use the time command, which is available for Unix-like operating systems such as Linux and OS X:
 $ time ./my-program
You should also try profiling your solutions. Ruby comes with a built-in code profiler if you give it the -rprofile argument, but it's rather slow. I prefer to install ruby-prof. So I can profile with:
 $ ruby-prof ./my-program.rb
Profiling is great because it will tell you exactly which part of your code is taking the longest to run, so you can focus on optimizing just the bottlenecks.

I highly recommend solving the same problems in different languages. This will not only help teach you other languages, it will show you how much faster or slower a language is compared to other languages. It will also show you how expressive one language is compared to another. Sometimes I use the exact same algorithm in C as I do in PHP, and the syntax is almost completely identical, only the C version runs light years faster, of course.

It's worth running your solved problem using different versions of the same language. For example, PHP 5.3 solves my Euler problems a lot faster than php 5.2. Ruby 1.9 solves them a lot faster than 1.8, and so on.

I solved a lot of Euler problems between 2007 and 2010. When I recently looked back at some old problems I solved, one thing that I'm really glad I did back then was write comments to myself in each source file telling me: 1) How long it took me to solve the problem 2) How fast it ran on whatever machine and language version I was using at the time and 3) which language I solved it in first.

One last thing; make sure you go to projecteuler.NET and not the .com. The .com is a really annoying spam website.

Thursday, October 27, 2011

Learning CoffeeScript With Unit Tests


CoffeeScript is a language that transcompiles to JavaScript and has syntax that looks more like Ruby or Python. In other words, it allows you to write JavaScript without writing JavaScript and with a lot less code. The generated JavaScript code even runs as fast, if not faster, than if you had written pure JavaScript.

I don't mind writing pure JavaScript but since I really like Python and Ruby, I figured I'd give a try since the syntax is familiar. CoffeeScript can even make jQuery even easier to write than it already is.

My Coworker Danny turned me on to using Koans to learn Ruby, and when he mentioned there's a CoffeeScript version, I immediately jumped on it.

Koans can aid in learning a new programming language. They're a Behavior Driven Development approach that turn learning into a kind of game where you fill in the blanks to make tests pass.

A CoffeeScript Koan consists of CoffeeScript code with Jasmine unit test files. The tests look like:
 # Sometimes we will ask you to fill in the values
 it 'should have filled in values', ->
   expect(FILL_ME_IN).toEqual(1 + 1)
You then compile the file (in this case AboutExpects.coffee) using the command-line coffee tool:
 $ coffee -c AboutExpects.coffee
which in turn creates the corresponding JavaScript file (in this case AboutExpects.js). If we were just writing CoffeeScript code, we could then run the .js file in a Web Browser, as usual. Or even execute the JavaScript file without a browser, if you have node.js installed, which we'll do in a minute:
 $ node yourFile.js
However, since we're doing Koans, we'll load the file using the bundled "KoansRunner.html" file, which loads our compiled .js file using the Jasmine Behavior Driven Development framework. This let's us know if our tests passed or failed.

Let's start by installing the CoffeeScript and the command-line compiler. Note that modern Ruby on Rails installs should already have CoffeeScript. For this tutorial I've only tested the following in Ubuntu Linux, but it should work for most Unix-like Systems. But you're always free to check for bundles for your system if you want to make it a little easier on yourself.

The coffee command-line tool is dependent on Node.js, so we'll need to install that first. Currently, the best way to install Node is to compile it yourself. So download it via the tarball or github repository, then run the usual:
$ ./configure && make && sudo make install
Now that Node is installed, we'll install the Node Package Manager (NPM):
 $ cd /tmp
 $ curl -O http://npmjs.org/install.sh
 $ sudo ./install.sh
Now you can install the coffescript command with:
 $ sudo npm install -g coffee-script
Once installed, typing coffee should show an interactive prompt like:
 coffee>
Type Ctrl-D to exit.

You're now ready to install the CoffeeScript Koans from the github repository. Assuming you're working from ~/src/:
 $ mkdir ~/src/koans
 $ cd ~/src/koans
 $ git clone https://github.com/sleepyfox/coffeescript-koans.git
 $ cd ~/src/koans/coffeescript-koans/
In the above screenshot image in this article, you can see I've split my Linux screen in half, with the top half a Web Browser running KoansRunner.html. The bottom half is AboutExpects.coffee open in Vim.

Note that the answers to the first two Koans are already filled out in my example. They're so overly simplistic that just by understanding those two answers you'll have learned as much as you otherwise would have, so don't feel cheated.

So now it will be your job to open koans/AboutExpects.coffee and fill in a test method with what you assume is the correct answer. Then compile it with:
 $ coffee -c koans/AboutExpects.coffee
and move the generated JavaScript file to the lib/koans directory and reload the KoansRunner.html file to see the new test results. Once you complete all the Koans in AboutExpects.coffee, you'll move onto the next Koans file, AboutArrays.coffee, and so on.

There are a couple of tips for making compiling and reloading easier. One tip is that at the root of the Koans directory, you can run a command called "cake", which was installed earlier during the coffee install process. You can verify this with:
 $ file $(which cake)
 /usr/local/bin/cake: symbolic link to `../lib/node_modules/coffee-script/bin/cake'
 $ file -L $(which cake)
 /usr/local/bin/cake: a node script text executable
Running:
 $ cake build
will compile all of the tests in the koans/ directory and automatically cp them to the lib/koans directory. This allows you to add a Vim keyboard mapping to your ~/.vimrc file, such as:

    nmap <Leader>c :!cake build<CR>

which lets you recompile the Koans by simplying typing \c in Vim. The "Leader" key on my system is a backslash, YMMV. Just make sure to run the shortcut from the root of the Koans directory so it can find the build file.

If you have Ruby and RubyGems installed, there's an even easier way to do this, using a "watch" command. The coffee command-line tool comes with an option called '-w', which watches for modified timestamps of files and then re-compiles the files automatically when they change. And the Koans come with a nice extension to this by including Ruby files called koans-linux.watchr, koans-win.watchr and koans-mac.watchr, respectively. To use it you need to install the watchr gem:
 $ gem install watchr
Now, if you were on a Linux machine, say, you would run this in a terminal:
 $ watchr koans-linux.watchr
Now you can edit and save your CoffeeScript koans and just hit refresh in your browser. The cake build step is taken care of automatically by the watchr!

Another thing that's nice to be able to do, is check our CoffeeScript code for syntax errors before we try to run it. This is known as "linting". The coffeescript command-line tool comes with an option called "-l" that lets you lint your files, but only if you have jslint installed first. So install it with:
 $ npm install jslint
At this point, you're breezing through the Koans and you start learning enough CoffeeScript that you actually start using it to write your JavaScript, and you open a coffee compiled .js file and you notice the JavaScript looks a little verbose. As a simple example, say you had written a Hello World function called hello.coffee like:
 sayHi = (name) ->
   return "Hello " + name

 console.log sayHi("Ryan")
and you compiled it and opened the .js file and noticed it looked like:
 (function() {
   var sayHi;
   sayHi = function(name) {
     return "Hello " + name;
   };
   console.log(sayHi("Ryan"));
 }).call(this);
As you might suspect, it's just there by default for global namespace cleanliness. You can either manually remove it, or compile your coffeescripts with "-b, --bare". Which would then look like simply:
 var sayHi;
 sayHi = function(name) {
   return "Hello " + name;
 };
 console.log(sayHi("Ryan"))
There is other verbosity such as it always declaring all variables with the var keyword. However, there's no good reason to take them things out since it's actually great to have CoffeeScript do all the tedious things for us that we often skip doing.

That's all for now. Please visit the main CoffeeScript and CoffeeScript Koans sites for more information.

Sunday, October 23, 2011

Approval Tests in PHP

Today, after hearing a talk by Llewellyn Falco, I decided to play with the Approval Tests library. There seems to be plenty of articles on using it with Java, .NET and Ruby but none on PHP, so I figured I'd write about it here.

Approval Tests are about simplifying the testing of complex objects, large strings, et al, where traditional Assert methods might fall short. The Library works with your existing testing framework, be it PHPUnit, Rspec, JUnit, NUnit, what have you. If you've never heard of Approval Tests before please read about them first and come back when you understand the basic concepts. This article focuses on how to use the Approval Tests library in PHP.

To install the Library I downloaded the tarball from the sourceforge download page and then unpacked it into my project's directory. It complained about me not having Zend_PDF so I installed the Zend Framework "minimal" addition. This required adding the Zend Framework's "Library" directory to my PHP include_path. You'll also need PHPUnit installed with PHPUnit_CodeCoverage.

Once installed, getting the approval tests library to work with PHP on my Linux box was tricky because (as of this writing at least) the PHP library seems to have no documentation and is rather incomplete. So I pulled up my sleeves and dug into the source code.

The automatic diff tool and the functionality to display a message for how to move the "received" file to the "approved" file didn't work. The reason is approvals/Approvals.php only had a case for 'html' and 'pdf' and defaulted to the PHPUnitReporter, which itself throws a runtime exception and thus short-cicuits the functionality that takes place in the approve() method.

To remedy this, I added a case for "txt" in the getReporter() method in approvals/Approvals.php. This got it to actually try to call the diff tool but it seems to assume you're using Mac OS X because approvals/reporters/OpenReceivedFileReporter.php does a system() call to the "open" command -- which in OS X will open files as if you double-clicked the file's icon but in Linux it runs 'openvt' -- which in this case will cause an error like "Couldn't get a file descriptor referring to the console." So I edited approvals/reporters/OpenReceivedFileReporter.php and changed:

 system(escapeshellcmd('open') . ' ' . 
    escapeshellarg($receivedFilename));

to:

 system("echo '#!/bin/sh' > /tmp/reporter.command; echo 'diff -u " . 
 escapeshellarg($approvedFilename) . " " .
 escapeshellarg($receivedFilename) .
 "' > /tmp/reporter.command; chmod +x /tmp/reporter.command; 
 /tmp/reporter.command");

That got everything working for me. I'm going to email the author about this and maybe submit a patch to get it working with vimdiff. For now "diff -u" was enough, as I was following the Do The Simplest Thing That Could Possible Work rule.

Now onto the PHP source code.

 <?php
 require_once 'approvals/Approvals.php';

 class Receipt {

   private $items;

   public function __construct() {
     $items = array();
   }

   public function addItem($quantity, $name, $price) {
     $this->items[] = array('name'=>$name, 'quantity'=>$quantity, 'price'=>$price);
   }

   public function __toString() {
     return $this->implode_assoc('=>', '|', $this->items);
   }

   private function implode_assoc($glue, $delimiter, $pieces) {
     $temp = array();

     foreach ($pieces as $k => $v) {
       if (is_array($v)) {
         $v = implode(',', $v);
       }
       $temp[] = "{$k}{$glue}{$v}";

     }

     return implode($delimiter, $temp);
   }
 }


 class ReceiptTest extends PHPUnit_Framework_TestCase {

   /**
    * @test
    **/
   public function Should_create_a_new_receipt() {
     $r = new Receipt();
     $r->addItem(1, 'Candy Bar', 0.50);
     $r->addItem(2, 'Soda', 0.50);
     Approvals::approveString($r);
   }
 }

Running the test the first time creates the file:

    ReceiptTest.Should_create_a_new_receipt.received.txt

in the current directory and fails the test. It's your job to view the generated txt file and decide if it looks right. If it does, rename it to:

    ReceiptTest.Should_create_a_new_receipt.approved.txt

Now when you rerun the test it will diff the current test's output against the approved.txt file's. If they're equivalent, then the test passes, if they're not it doesn't and it's up to you to diff the received and approved files for what the differences are and figure out how to get your test to pass again.

For example, the first time you run the test, it will generate the "received.txt" with the string:

    0=>Candy Bar,1,0.5|1=>Soda,2,0.5

If you rename the file to its approved.txt equivalent, change the quantity of Sodas to 3 and rerun the test, it will fail because it would create another received.txt to diff against the approved.txt but this time the received file will contain:

    0=>Candy Bar,1,0.5|1=>Soda,3,0.5

I hope you approve this article.

Thursday, September 29, 2011

The Bowling Game Kata in PHP

I did the famous Bowling Game Kata and converted it from Java to PHP, and used PHPUnit for unit tests, and thought I'd share my code for anyone who wants to see it.

If you run the tests like:
 $ phpunit --testdox BowlingTest.php
you should see the tests all pass like:

    Bowling
       [x] Should roll gutter game
       [x] Should roll all ones
       [x] Should roll one spare
       [x] Should roll one strike
       [x] Should roll perfect game
 <?php 
      
 class Game
 { 
   private $rolls = array();
  
   public function roll($pins) {
     $this->rolls[] = $pins;
   } 
  
   public function score() {
     $score = 0;
     $rollsMax = count($this->rolls);
     $firstInFrame = 0;
  
     for ($frame = 0; $frame < 10; $frame++) {
       if ($this->isStrike($firstInFrame)) {
         $score += 10 + $this->nextTwoBallsForStrike($firstInFrame);
         $firstInFrame++;
       } else if ($this->isSpare($firstInFrame)) {
           $score += 10 + $this->nextBallForSpare($firstInFrame);
           $firstInFrame += 2;
       } else {
         $score += $this->twoBallsInFrame($firstInFrame);
         $firstInFrame += 2;
       }
     }
  
     return $score; 
   } 
  
   public function nextTwoBallsForStrike($firstInFrame) {
     return $this->rolls[$firstInFrame + 1] + $this->rolls[$firstInFrame + 2];
   }

   public function nextBallForSpare($firstInFrame) {
     return $this->rolls[$firstInFrame + 2];
   } 
  
   public function twoBallsInFrame($firstInFrame) {
     return $this->rolls[$firstInFrame] + $this->rolls[$firstInFrame + 1];
   }

  
   public function isStrike($firstInFrame) {
     return $this->rolls[$firstInFrame] == 10;
   }

   public function isSpare($firstInFrame) {
     return $this->rolls[$firstInFrame] + $this->rolls[$firstInFrame+1] == 10;
   }

   public function rollSpare() {
     $this->roll(5);
     $this->roll(5);
   }
 }


 class BowlingTest extends PHPUnit_Framework_TestCase {
   private $g;

   public function setUp() {
     $this->g = new Game;
   }

   /**
    * @test
    */
   public function Should_roll_gutter_game() {
     $this->rollMany(20, 0);
     $this->assertEquals(0, $this->g->score());
   }

   /**
    * @test
    */
   public function Should_roll_all_ones() {
     $this->rollMany(20, 1);
     $this->assertEquals(20, $this->g->score());
   }

   /**
    * @test
    */
   public function Should_roll_one_spare() {
     $this->g->rollSpare();
     $this->g->roll(3);
     $this->rollMany(17, 0);
     $this->assertEquals(16, $this->g->score());
   }

   /**
     * @test
    **/
   public function Should_roll_one_strike() {
     $this->rollStrike();
     $this->g->roll(3);
     $this->g->roll(4);
     $this->rollMany(16, 0);
     $this->assertEquals(24, $this->g->score());
   }

   /**
    * @test
    **/
   public function Should_roll_perfect_game() {
      $this->rollMany(12, 10);
      $this->assertEquals(300, $this->g->score());
   }

   public function rollMany($n, $pins) {
     for ($i = 0; $i < $n; $i++) {
         $this->g->roll($pins);
     }
   }

   public function rollStrike() {
     $this->g->roll(10);
   }
 }
 

Sunday, September 18, 2011

Creating Code Snippets for any Programming Language

A snippet is a piece of often-typed text (for loops, function definitions, etc.) that you can insert into your document using a trigger word followed by a [Tab]. The snipMate plugin for Vim gives it TextMate style snippet creation abilities for literally any programming language you happen to use. It comes with many default snippets and you can easily tweak them or create your own.

The bottom line is that snipMate will save you a ton of time and is far more powerful than simple code-completion. Some people spend a lot of money on individual IDEs that only work with one or two languages. In this article I will show examples of how Vim can create powerful snippets in C, PHP, Python, Ruby, JavaScript, HTML, and more.

The perfect first example of snipMate's capabilities is generating a for loop by typing nothing more than:
 for[Tab]
Which expands to:
 for (i = 0; i < count; i++) { 
     // code
 }
If you were editing a C language file, anyway. The snipMate plugin is context sensitive, based off of the file type you're editing. For example, if you were editing a PHP file instead, then typing for[Tab] would have produced a PHP for loop:
 for ($i = 0; $i < count; $i++) {
     // code...
 }
What's more, is after expanding to a full for loop it then places your cursor on the first likely edit point - in this case it places your cursor on the word "count" and puts Vim in SELECT mode so you cans start typing to replace it with another word such as "$max", or whatever you require. If you don't want to change the selected word just hit [Tab] without changing it. Typing [Tab] again jumps you to the next edit point, which in this case goes back to the first "$i" in the loop. From there, if you were to type x, it would replace all the $i's in the loop with $x's. Typing [Tab] from there will jump your cursor to the "++" in the "$x++", in case you wanted to change it to something else like "+=2". Typing [Tab] one last time will take you down to the "// code" line. You get the picture.

To scroll backwards, use [Shift+Tab], as you might expect.

You can even enbable multiple filetypes at the same time in Vim by chaining them with dots. For example:

    :set ft=php.html

Will let you use both the PHP and HTML snippets on the file you're editing.

How does this work? Well, behind the scenes there are snippet files. In your ~/.vim/snippets/ directory exists the files: c.snippets (for C code), php.snippets (for PHP code), and so on. The plugin knows what filetype you're editing and then loads the corresponding snippet file based on the prefix of the file name. So if you're editing a PHP file, it looks in the snippets directory with file names starting with "php".

This means you can easily create your own custom additions. For example, to create more PHP snippets, you could either add them to the existing php.snippets file, or better yet, create your own new file called "php-mine.snippets". In it, you input snippets that don't come with the default snippets file. For example, I really wanted to be able to just type th[Tab] to create $this->. So in php-mine.snippets, I made the snippet:
 snippet th
     $this->${1}
It's important that you insert actual Tabstops (\t) when you indent in the snippets file. In Vim, typing Ctrl+v Tab will insert a real tabstop.

The "${1}" in the snippet indicates to snipMate where you want the cursor to jump to after the snippet expands. In the above example, I'm telling it to land directly after the "->". To tell it where to jump when a user starts pressing [Tab] you simply place it where you want and give it the corresponding number. For example: "${2}", "${3}", etc. In order to highlight certain text when your cursor jumps there, then add a colon (:) after the number followed by the text to select: ${2:foo} will jump your cursor to the string "foo", and highlight it.

Note that if you create multiple snippets with the same name, then Vim will prompt you with a drop down selection list to chose from.

Another PHP snippet you might create is:
 snippet substr
     substr(${1:string $string}, ${2:int $start} ${3:[, int $length]})
Which expands to:

    substr(string $string, int $start [, int $length])

This is useful if you often forget the parameters certain functions take.

I also like to create another snippets file called "php-unit.snippets" which contains my PHPUnit framework snippets. In here, I have snippets like:
 snippet test
     /**
     * @test
     **/
     public function ${1:}() {
         ${2:}
     }${3:}
Which, typing test[tab], expands to:

    /**
    * @test
    **/
    public function () {
    
    }

A more involved example is my getMockBuilder() method snippet:
 snippet getmockbuilder
     ${8:}$this->getMockBuilder('${1:string $OriginalCLassName}')
         ->setMethods(${2:array $methods})
         ->setConstructorArgs(${3:array $args})
         ->setMockClassName(${4:string $name})
         ${5:->disableOriginalConstructor(})
         ${6:->disableOriginalClone()}
         ${7:->disableAutoload()}
         ->getMock();
Expands to, when you type getmockbuilder[Tab]:

    $this->getMockBuilder('string $OriginalCLassName')
              ->setMethods(array $methods)
              ->setConstructorArgs(array $args)
              ->setMockClassName(string $name)
              ->disableOriginalConstructor()
              ->disableOriginalClone()
              ->disableAutoload()
              ->getMock();


Tip: To easily search through all the existing snippets of a .snippets file, type this search query in Vim:

     /snippet \zs.*

Some useful Python snippets:
    import             = imp[tab]
    function template  = def[tab]
    for loop           = for[tab]
(Also see the Python code-completion plugin for Vim I wrote called Pydiction.)

Some other useful PHP snippets include:
    php           = <?php  ?>
    echo          = ec[tab] 
    fun           = public function FunctionName() ...
    foreach       = foreach[tab]
    if            = if (/* condition */) { ...
    ife           = if/else
    else          = else { ...
    elseif        = elseif () { ...
    switch/case   = switch[tab]
    case          = case 'value': ...
    t             = $retVal = (condition) ? a : b;
    while         = wh[tab]
    do/while      = do[tab]
    Super Globals = $_[tab]
    docblock      = /*[tab]
    inc1          = include_once
    req           = require
    req1          = require_once
    $_            = List of $_GET[''], $_POST[''], etc
    globals       = $GLOBALS['variable'] = something;
    def           = define('')
    def?          = defined('')
    array         = $arrayName = array('' => );
    /*            = dockblock: /**  *  **/
    doc_h         = file header docblock
    doc_c         = class docblock
    doc_cp        = class post docblock
    doc_d         = constant docblock
    doc_fp        = function docblock
    doc_v         = class variable docblock
    doc_vp        = class variable post docblock
    doc_i         = interface docblock
Some Bash snippets:
#![tab]
expands to: #!/bin/bash
if[tab]
expands to:

        if [[ condition ]]; then
            #statements
        fi


For JavaScript:
    get[Tab]  =  getElementsByTagName('')
    gett[Tab] =  getElementById('')
    timeout   =  setTimeout(function() {}, 10;
    ...
For Ruby:
    ea      =  each { |e|  }
    array   =  Array.new(10) { |i|  }
    gre     =  grep(/pattern/) { |match|  }
    patfh   =  File.join(File.dirname(__FILE__), *%2[rel path here])
    ...
In a previous article I mentioned using Zen Coding for super fast HTML creation. Well, you can also create HTML with snipMate. This is useful when you need to do something that Zen Coding cannot do. For instance, snipMate has all the HTML Doctypes:
    docts  =  (HTML 4.01 strict)
    doct   =  (HTML 4.01 transitional)
    docx   =  (XHTML Doctype 1.1)
    docxt  =  (XHTML DocType 1.0 transitional)
    docxs  =  (XHTML Doctype 1.0 Strict)
    docxf  =  (XHTML Doctype 1.0 Frameset)
    doct5  =  (HTML 5)

Other HTML snippets include:
    head[tab]
    title[tab]
    script[tab]
    scriptsrc[tab]
    r[tab]
    base[tab]
    meta[tab]
    style[tab]
    link[tab]
    body[tab]
    table[tab]
    div[tab]
    form[tab]
    input[tab]
    textarea[tab]
    mailto[tab]
    h1[tab]
    label[tab]
    select[tab] and opt[tab] and optt[tab]
    meta[tab]
    movie[tab]
    nbs[tab]
That's all for now. If you want to share snippets you made please link to them in the comments section below.

Saturday, September 17, 2011

Zen Coding Your HTML, XML and CSS

Zen Coding is a plugin that works with many editors (Vim, Notepad++, TextMate, etc) for writing HTML (and other structured code) very quickly and efficiently. It's currently at version 0.7 but has been very stable for me.

The plugin expands abbreviated code you write. For example, it can expand:

    html>head>title

to:

    <html>
      <head>
         <title></title>
        </head>
    </html>


Installing the Zen Coding plugin for Vim is as easily as downloading zencoding.vim and installing it to your $HOME/vimfiles/ftplugin/html Directory. Now when you're editing an HTML file (:set ft=html) you can type an abbreviation like:

    html:5

Then, while in either insert or normal mode, type:

    Ctrl+y,

Again, that's ^y followed by a comma. And that should expand the HTML 5 template:

    <!DOCTYPE HTML>
    <html lang="en">
        <head>
            <title></title>
            <meta charset="UTF-8">
        </head>
        <body>
            
        </body>
    </html>


There's a lot more you can do with it such as repeating tags. For example, say you want an unordered list containing four list elements with a class of incrementing items. Typing:

    ul>li.item$*4 Ctrl+y,

Should expand to:

    <ul>
      <li class="item1">_</li>
      <li class="item2"></li>
      <li class="item3"></li>
      <li class="item4"></li>
    </ul>


The "*" multiplies the element before with the number after it. And the "$" gets replaced by an incrementing number. Pretty cool, huh?

Notice the underscore inside the first LI tag. This is where your cursor would end up if you run this expression. Zen coding allows you to have jump to edit points. For example, typing "Ctrl+y n" would jump your cursor to to the next LI element. Typing "Ctrl+y N" jumps to the previous element.

Say you want to add a tag but not nest it. For example:

    <p></p>
    <a href=""></a>

Then just add a "+" (plus sign) between the tags to separate:

    p+a Ctrl+y,

You can delete any tag you're in by typing: Ctrl+y k

To create any tag with a closing and end tag, just type the name of the tag:

    foo Ctrl+y,

becomes:

    <foo></foo>

To create:

    <script type="text/javascript"></script>

Just type:

    script Ctrl+y,

To make a DIV with an id of "foo": div#foo Ctrl+y,

To create a nested DIVs. You could, for example type:

    div#foo$*2>div.bar Ctrl+y,

Which would expand to:

    <div id="foo1">
      <div class="bar">_</div>
    </div>
    <div id="foo2">
      <div class="bar"></div>
    </div>


To create tags that close themselves, such as a BR tag:

    br Ctrl+y,

Becomes:

    <br />

To comment out a block of HTML, just move your cursor to the start of the block of HTML and type: Ctrl+y/

If you visually select the block and type Ctrl+y, it will prompt for a tag to wrap the block inside of. You can even enter expressions here to wrap text into HTML. For example, if you had the text:

    line1
    line2
    line3

You could highlight it and type Ctrl+y, ul>li* to convert it to:

    <ul>
      <li>line1</li>
      <li>line2</li>
      <li>line3</li>
    </ul>


You can also apply "filters" at the end of your expressions. For example, adding "|e" will escape your HTML output so that >'s become <'s and so on. So typing a|e Ctrl+y, expands to:

    &lt;a href=""&gt;&lt;/a&gt;

Another filter called "|c" adds HTML comments to important tags, such as tags with ID and/or classes. There's even a HAML filter.

I'll leave you with one more neat thing you can do with Zen Coding. You can add text to your expressions that will be placed in the corresponding position. For example:

    p>{Click }+a{here} Ctrl+y,

Expands to:

    <p>
      Click <a href="">here</a>
    </p>


Enjoy!

Friday, September 16, 2011

Refactoring with Vim Macros

Automation is what computers do best but we often forget to take advantage of this fact. I don't know about you but I love to take shortcuts when it gets me to the same place. In practice though, it often takes a little extra work up front, but the small amount of effort comprises the majority of the end result.

There are some refactoring commands that you may wish to repeat in the Vim editor but don't want to make a permanent mapping for because they're only needed temporarily for the current file. And a complicated regular expression would take you too long to get right - especially with Vim's non-standard regex engine - and you may not feel it safe to run even if you did manage to figure it out.

Fortunately, Vim also supports macros. Knowing just the Vim commands that you already know, plus a couple of commands to record and play them, you can create powerful macros with very little effort.

To record a macro in Vim, type qq to begin recording, followed by the series of commands to record, then "q" to stop recording. You then type @q to execute the recorded macro.

Let's start with a very simple example. Say you have a file with a bunch of lines:

    line1
    line2
    line3
    line4
    ...

and you want to change the first letter of each line to be a capital letter. You might normally do this all manually by going to the beginning of each line and typing ~ (tilde in vim toggles the case of the character under the cursor). Then you might type j repeatedly to scroll down to each line and then type . to repeat the command. I've seen people do stuff like this on lines with 50+ lines and they just sit there like a robot typing the same thing over and over. Well, it doesn't have to be that way. Instead, you could just go to line1 and type:

    qq0~j<ESC>q

That will run the command on just the current line number and position you to the next line so you can easily run the macro. Note that the 0 (zero) I added to the macro is there to jump to the beginning of the line so we always only capitalize the first letter. Now you're ready to repeat the macro on the rest of the lines by typing:

    3@q

The '3' is for the number of times to repeat the macro.

As another example say you need to edit an PHP file that has a bunch of ugly, yet similar, lines like:

    if (@$FOO) someFunction($foo);

and you want to refactor these lines to be like:

    if (isset($foo) && !empty($foo)) {
      someFunction($foo);
    }


to do this, you could type the following (Don't worry if you don't understand it yet, I'll break it down in a minute):

  0f@xyeiisset(<ESC>f)i) && !empty(<ESC>pa)<ESC>la {<ENTER><ESC>o}<ESC>

so now all you need to do to this record it is add two q's to the beginning and one q to the end, like so:

    qq0f@xyeiisset(<ESC>f)i) && !empty(<ESC>pa)<ESC>la {<ENTER><ESC>o}<ESC>q

Now you can put your cursor anywhere on a line containing the if statement you want to refactor and type @q and it will run the macro. To repeat the macro, go to another line and type @@.

Okay, let's break down the command. It may need to be tweaked depending on your Vim setup, but on my set up it works like this:

    qq begins recording
    0 jumps to the beginning of the line
    f@ jumps to the @ sign.
    x deletes the @ sign
    ye yanks from the cursor to the end of the word (copies $foo)
    i puts you in INSERT mode
    isset( inserts the text "isset("
    <ESC> escapes you back to normal mode
    f) jumps to to the closing parenthesis
    i) && !empty( inserts the text ") && !empty("
    <ESC> escapes you back to normal mode
    p pastes the text "$foo"
    a) inserts the closing parenthesis
    <ESC> escapes you back to normal mode
    la moves your cursor passed the ")" and into insert mode
    { inserts the opening brace
    <ENTER< inserts a newline, pushing "somefunc($foo)" to the next line
    <ESC> escapes you back to normal mode
    o jumps your cursor to the next line and puts you in insert mode
    } inserts a closing brace (which should auto-indent depending on your setup)
    <ESC> escapes you back to normal mode
    q ends recording

This may seem intimidating on first glance and make you think it's more trouble than it's worth but the beauty of Vim is how quickly you can type commands. You just need to try it a few times to get the hang of it, trust me.

In the above examples I used qq to begin recording. This is just a convention for single macros. You can actually store multiple macros at the same time by storing them in different registers. For example qa begins recording to the register a, which you can then run with @a. You could then create another macro with qb and run with @b, and so on.

You can even run a macro on a specific range of lines, say 20 to 30, by doing:

    :20,30norm! @q

Similarly, you could visually select just the lines you want to run the macro on and then type"

    :norm @q

If you remember this simple strategy of recording each series of commands you plan to repeat, then you're golden. If you're going to have to type the commands either way, then recording them is very little effort compared to manually typing the commands over and over.

Followers