<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Jack Kinsella</title>
 <link href="http://www.jackinsella.ie/atom.xml" rel="self"/>
 <link href="http://www.jackkinsella.ie/"/>
 <updated>2011-12-15T11:03:05-08:00</updated>
 <id>http://www.jackkinsella.ie/</id>
 <author>
   <name>Jack Kinsella</name>
 </author>
 
 <entry>
   <title>Automating Popularity</title>
   <link href="http://www.jackkinsella.ie/2011/12/14/automating-popularity.html"/>
   <updated>2011-12-14T00:00:00-08:00</updated>
   <id>http://tom.preston-werner.com/2011/12/14/automating-popularity</id>
   <content type="html">&lt;p&gt;Two years ago I wrote a program that logged into my Facebook account and pretended to be me. I wanted to test the hypothesis that &lt;strong&gt;automatic tools could make someone more popular&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If I could build a script that caused more friends to get in touch with me, then my hypothesis would be proven true. If, instead, the script had no effect on my popularity or was detected as a fraud by the people in my network, then my hypothesis would be proven false.&lt;/p&gt;
&lt;p&gt;Before I carried out the experiment I studied some social psychology. According to the texts, a new acquaintance becomes a friend when they appear frequently in our lives; when they share our interests, beliefs, and background; and when we know that they return our affinity for them by liking us back.&lt;/p&gt;
&lt;p&gt;Newly informed, I modeled these concepts by creating a script that logged into my Facebook account and automatically liked the status updates, photos and comments of my friends, covering up the evidence as it went.&lt;/p&gt;
&lt;p&gt;Five days later the results came in. Listen to my talk, recorded at &lt;a href=&quot;http://www.ignitethewest.com/&quot;&gt;Ignite the West&lt;/a&gt;, in Galway, Ireland for the full story:&lt;/p&gt;
&lt;p&gt;&lt;iframe style=&quot;text-align:center;&quot; width=&quot;630&quot; height=&quot;472.5&quot; src=&quot;http://www.youtube.com/embed/PbVlUVMRGTI&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://twitter.com/#!/meetforeal&quot;&gt;Ellen Dudley&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/#!/amonter5&quot;&gt;Adrian Avendano&lt;/a&gt;, two awesome people changing the world for the better, for organising Ignite the West.&lt;/p&gt;
&lt;p&gt;PS If you have a research project or app idea in this area, &lt;a href=&quot;/rails-developer-london.html&quot;&gt;I can make it happen&lt;/a&gt;&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Janki Method</title>
   <link href="http://www.jackkinsella.ie/2011/12/05/janki-method.html"/>
   <updated>2011-12-05T00:00:00-08:00</updated>
   <id>http://tom.preston-werner.com/2011/12/05/janki-method</id>
   <content type="html">&lt;p&gt;This is a guide to becoming a productive programmer quickly. In his book &lt;em&gt;Outliers&lt;/em&gt;, Malcolm Gladwell told the world it takes 10,000 hours to master something. Practice three hours a day, and you will shine in ten short years. Millions of readers felt inspired since they too could become the next Bill Gates, if only they put in the hours. As the days turned to months we discovered that 10,000 hours was a lot longer than we anticipated. Limitless potential transformed into fantasy about what might have been.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Janki Method&lt;/strong&gt; is an attempt to shorten the time needed to learn programming. It grew out of my impatient dream to build an automated web business that would free me financially, geographically and temporally. I didn&amp;#8217;t want to wait 10,000 hours. I suspect you don&amp;#8217;t either.&lt;/p&gt;
&lt;p style=&quot;float:right;&quot;&gt;&lt;img src=&quot;/images/janki/anki.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Well-intentioned learners don&amp;#8217;t always learn quickly, despite their smarts and enthusiasm. For most, eventual ability is determined by the volume of time expended. Malcolm&amp;#8217;s 10k sounds right.&lt;/p&gt;
&lt;p&gt;You’ve read that learning by doing is better than passive reading; that expressing ideas in writing forces understanding; that knowledge needs constant revision to stay fresh; that creativity comes from linking disparate ideas; and that your past mistakes are your best teachers. How many of these ideas do you apply to your learning efforts?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Janki Method&lt;/strong&gt; is built on the assumption that Malcolm’s 10k to mastery can be hastened if you take a focused approach to learning. The core of Janki Method is the use of a spaced repetition flashcard system, &lt;a href=&quot;http://ankisrs.net/&quot;&gt;Anki&lt;/a&gt;, programmed by the brilliant Damien Elmes.&lt;/p&gt;
&lt;p&gt;By following my approach, I believe that any intelligent and disciplined reader can achieve proficiency* in a given field of programming (e.g. web applications, iPhone applications) in less than 12 months.&lt;/p&gt;
&lt;p&gt;I call this the &lt;strong&gt;Janki Challenge&lt;/strong&gt;, and I invite you to take part.&lt;/p&gt;
&lt;h2 class=&quot;section-title&quot;&gt;Problems With Learning&lt;/h2&gt;
&lt;h2&gt;Problem 1: We Forget Too Quickly&lt;/h2&gt;
&lt;p&gt;Have you ever spent a week studying for an exam, only to forget 90% of what you learned within 2 months and everything else within a year?&lt;/p&gt;
&lt;p&gt;Forgetting impedes learning knowledge-intensive skills such as programming. You need to remember various languages, solutions, libraries and gotchas if you want to build large applications. Because technical material can be so abstract and dry, you forget particularly quickly.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The first rule of &lt;strong&gt;Janki&lt;/strong&gt; boosts your memory:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Every time you learn something new create a question and answer flashcard and add this card to Anki.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Anki is a Spaced Repetition System. Most algorithms make computers efficient; Anki makes you efficient.  Using the minimal number of repetitions necessary for permanent retention, Anki drills flashcards into your long-term memory.&lt;/p&gt;
&lt;p&gt;Begin by creating a deck of flashcards called, say, computer science. A deck contains many cards, and each card consists of a question and an answer. You tag these cards with the categories that best describe their contents. For example, one card might be tagged with &amp;#8216;Rails&amp;#8217;, and another with ‘SQL&amp;#8217;. Each card can have numerous tags, something useful given how technologies frequently overlap.&lt;/p&gt;
&lt;p&gt;Over time you will build up a repository of knowledge on programming, cleanly categorized, easily searchable and regularly backed up in the cloud. Keeping a repository like is useful, but it doesn’t do anything to help you keep the knowledge inside your head. The key to this is doing your Ankis.&lt;/p&gt;
&lt;p&gt;Every morning Anki calculates which cards you risk forgetting, and then prompts you to review these cards. Doing your Ankis only takes a few minutes per day, since you only need to review a fraction of your deck on any given day.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/daily-reviews.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;For every card you review, Anki shows you the question side with the answer side initially blocked out. Your job is to answer the question in your head, and then reveal the answer and check whether you got it right. After you answer, four buttons appear at the bottom of the screen: “again”, “good”, “easy” and “very easy”.  Assess how easily you could recall that card and then press the appropriate button. Based on which button you press, Anki determines when next to show you that card, so answering honestly is crucial if you want the algorithm to work.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/question1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Do this every day and you will not forget.&lt;/p&gt;
&lt;h2&gt;Problem 2: We Give Up Too Soon&lt;/h2&gt;
&lt;p&gt;Most people fail to learn programming for the same reason they don’t get good at playing guitar: they give up too soon. Although they practice hard for the first few weeks, they soon lose motivation, and give up before they get results.&lt;/p&gt;
&lt;p&gt;Trying to learn using a rhythm of intense activity over short periods of time followed by long pauses is problematic. Your mind needs time to absorb what it learns, so learning skills cannot be condensed into a weekend. By accepting this reality and using a learning approach that emphasizes incremental daily effort, you will be less likely to burn out and more likely to succeed.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The second rule of &lt;strong&gt;Janki&lt;/strong&gt; encourages a commitment to daily learning:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“You must use Anki every single day- including weekends and holidays &amp;#8211; and commit to doing so indefinitely.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Doing your Ankis must hold the same force of habit as brushing your teeth, and you should feel naughty if you ever miss your Ankis.&lt;/p&gt;
&lt;p&gt;Rule 2 isn’t as demanding as it might at first seem.  After a few months of practice you will be able do your Ankis in 5-8 minutes. Finding that time shouldn’t be a problem either, since Anki is available on smart-phone, meaning you can review while you walk to work, sit in the bus or have a spare minute at the office. Anki even synchronizes the state of your decks across all your devices, so changes to your desktop deck will be reflected across all of your devices.&lt;/p&gt;
&lt;h2&gt;Problem 3: We Learn Out Of Context&lt;/h2&gt;
&lt;p&gt;Learning out of context is wasteful. Reading a textbook from cover to cover may be interesting, but if those concepts are not relevant to the technical problems you currently face, then you will lack the mental context needed to assimilate that knowledge effectively. Incomplete understanding and wasted effort ensues.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The third rule of &lt;strong&gt;Janki&lt;/strong&gt; keeps you focused on what is important in the moment:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Learn in context. Pick a project, and learn only what you need to get it done.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;When I was writing this blog post I didn&amp;#8217;t know how to add images in the Textile language.&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/new-card1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Step 1: I Googled it.&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/new-card2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Step 2: I tried the code out by adding an image to the post.&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/new-card3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Step 3: After checking that it worked, I added my new technique to my Anki Deck.&lt;/h3&gt;
&lt;h2&gt;Problem 4: We Think We Can Learn Without Doing&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“I learned about sex the hard way – from a book.”&lt;br /&gt;
&lt;strong&gt;Eddie Izzard&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like sex, programming is better and more enjoyably mastered through practice. Learning without practice insulates you from reality.&lt;/p&gt;
&lt;p&gt;When you read about programming without trying out the code, you form an internal representation that is incomplete, poorly understood, and difficult to apply practically.&lt;/p&gt;
&lt;p&gt;You will fail to notice critical details. Many things may seem trivial when you first read about them in a textbook. Maybe it&amp;#8217;s the placing of quotations around a parameter to a function, or rules about where whitespace is allowed. These overlooked points can often be critical in practice, and anything less than complete understanding will cripple hour productivity. It is only by trying code out that you will notice the nuances of these rules, and really understanding the language, techniques, and commands in question.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The fourth rule of &lt;strong&gt;Janki&lt;/strong&gt; grounds knowledge in reality:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Only add a card to your deck after having tried to use the item of knowledge therein.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Say you are working on an application powered by an &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; database. To build it you will need to refer to literature on database design and &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; (a query language for selecting records from database tables). As you work on the application you will be exposed to new concepts. Try out each new nugget of knowledge before adding it to your Anki deck. If, for example, you read about how to delete a row in a database table, then you should try deleting an actual row in your database before creating the Anki card detailing that &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; query.&lt;/p&gt;
&lt;h2&gt;Problem 5: We Make More Mistakes Than We Need To&lt;/h2&gt;
&lt;p&gt;/* Our past mistakes serve as excellent memory aids.  This is a major reason why we learn by doing. That said, not all past mistakes are equally effective at teaching us lessons; there is a correlation between the emotional impact of an error and the length of time that lesson will remain in memory. */&lt;/p&gt;
&lt;p&gt;Say you make a big mistake. You accidentally push incomplete code to a live server, taking your app down for 12 hours. You panic to fix it, and as the customer complaints flood in, you feel stupid and embarrassed. This emotional punishment serves as a strong reminder of your error, and you will be more careful when pushing code to a server in future.&lt;/p&gt;
&lt;p&gt;Errors with emotional impact are, thankfully, rare, and you are unlikely to need &lt;strong&gt;Janki Method&lt;/strong&gt; to learn from these. But what about the rest of the mistakes we make, where the emotional element is diminished or even absent? We may need to make these mistakes many times before eventually learning our lesson.&lt;/p&gt;
&lt;p&gt;Mistake repetition is the number of times you need to commit a particular mistake over a lifetime before learning a permanent lesson. Because mistakes are costly, embarrassing and potentially career threatening, it is sensible to minimize their occurrence. Bosses, customers and co-workers understand a first time mistake, and all but the most unreasonable will forgive you. They will not, however, feel so forgiving the second or third time you get the same thing wrong.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The fifth rule of &lt;strong&gt;Janki&lt;/strong&gt; method minimizes mistake repetition.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Every time you make a mistake carry out a post-mortem and try to figure out the lessons in the experience. Think about what you would need to know to prevent that mistake from occurring again, and turn this insight into new flashcards.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;By applying this rule you will substitute real world mistakes with Janki reviews, and you will consequently learn from your mistakes more quickly and with less embarrassment and real world error.&lt;/p&gt;
&lt;p&gt;Ankifying your past failures doesn’t just prevent their repetition.  It also helps you understand your domain, since the act of performing a post-mortem analysis and examining the underlying causes of your error encourages deep thought.  Instead of just creating the cards you need to prevent that particular error, you might immunize yourself against that entire class of error.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/bug2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Every mistake becomes a learning experience. Messing up still sucks, but you feel a small sense of victory knowing that you’ve just found a way to improve, and you will feel assured by the certainty that you will never make that mistake again.&lt;/p&gt;
&lt;h2&gt;Problem 6: We Do Not Reflect On The Big Picture&lt;/h2&gt;
&lt;p&gt;By following the initial five rules of &lt;strong&gt;Janki Method&lt;/strong&gt; you will quickly become proficient with the low level details of programming: then name and use cases of functions and commands, their expected inputs and expected outputs, solutions to common bugs, and techniques for keeping your code organised.&lt;/p&gt;
&lt;p&gt;As your experience grows you will be faced with bigger questions, such as structural decisions about your application, techniques to minimize complexity, workflows for managing simultaneous versions of your code, and the tradeoff between code performance and elegance. Answering these questions requires deep knowledge and sizable experience, and for this reason you must never miss an opportunity to grow your knowledge in these overarching issues.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The sixth rule of &lt;strong&gt;Janki&lt;/strong&gt; method encourages regular critical reflection:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“At the end of every project ask yourself what lessons you learned and what you would do differently if you were to repeat the project with the benefit of hindsight.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;After a large project, such as completion of a new app, take some time to reflect. Ask yourself big questions, such as:&lt;/p&gt;
&lt;p&gt;*	Did I waste time going down any dead ends? Is there anything I could do in future to help me foresee these, and prevent them from happening again?&lt;br /&gt;
*	Did I choose the right technologies? Can I come up with a schema to help me make the right choices next time?&lt;br /&gt;
*	Did I accurately estimate the time required?&lt;br /&gt;
*	Could I have built simpler architecture? Could I have figured this out earlier?&lt;br /&gt;
*	Can I create a checklist to ease development of that kind of feature in future?&lt;/p&gt;
&lt;p&gt;Some of these questions will be difficult to answer because you have to run through alternatives in your head, thinking about the benefits and tradeoffs of each. This effort is worthwhile since sensible architectural decisions prevent wasted effort. Without active reflection you will be less likely to notice these project level patterns, and so your wisdom will grow more slowly than it otherwise would.&lt;/p&gt;
&lt;h2&gt;Problem 7: We Let Our Knowledge Representations Grow Messy&lt;/h2&gt;
&lt;p&gt;Like a front lawn left idle, your Anki decks can grow ugly. Perhaps one of the programming languages you previously learned has changed dramatically in version 2.0 and now a percentage of your cards are invalid. Perhaps some of your cards are no longer worthy of keeping in periodic review– their usefulness doesn’t justify the cumulative revision time needed.&lt;/p&gt;
&lt;p&gt;As you learn, you will discover simpler ways to understand concepts; without updating your cards to reflect these improved paradigms you risk losing these insights forever. Often a group of cards can be replaced with a single card on a higher order concept.&lt;/p&gt;
&lt;p&gt;Sometimes you will see links between cards in your deck. If you note the connection between these cards you create multiple neural paths to the same item of knowledge. If one path were to fail, you could still arrive at and trigger that knowledge from another route. The ability of mind maps to help you remember works using a similar idea. By looking for and noting these connections in your decks this you add a layer of redundancy to your knowledge representation that further insures against future forgetting,&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The seventh rule of &lt;strong&gt;Janki&lt;/strong&gt; keeps your decks in shape.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Delete or modify any incorrect, outdated, difficult to remember, incomplete or unnecessary cards. Update existing cards as improved understanding dawns.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;The following shows a poor understanding of Git, later updated with a more nuanced understanding.&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/poor-understanding.png&quot; alt=&quot;&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;/images/janki/better-understanding.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Problem 8: We Do Not Reference Primary Sources&lt;/h2&gt;
&lt;p&gt;Graphic designers, artists, architects and other creatives keep scrapbooks of designs they like. Later, when working on a project, they draw inspiration from these same scrapbooks.&lt;/p&gt;
&lt;p&gt;As a programmer your primary source of inspiration will be other people’s code. Download open source projects (e.g. on &lt;a href=&quot;http:www.github.com&quot;&gt;Github&lt;/a&gt;) and read through the code. Look up parts you don’t understand, and create new cards as necessary. Get a pen and paper, and sketch out the paths through the program. What are the inputs, and what are the expected outputs? What happens to the data as it moves through the program? Why was it designed in this way? What techniques were used?&lt;/p&gt;
&lt;p&gt;By reading code you will be exposed to various styles and of programming and solutions to programming problems. You will see things you like, and lots of things you don’t like. With time you will find your own style.&lt;/p&gt;
&lt;div class=&quot;janki-rule&quot;&gt;
&lt;p&gt;&lt;em&gt;The eighth rule of &lt;strong&gt;Janki&lt;/strong&gt; encourages you to use your readings of other people’s code as a source of learning:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“Read code regularly. If you come across something interesting – be that an algorithm, a hack, or an architectural decision &amp;#8211; create a card detailing the technique and showing the code.”&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 class=&quot;section-title&quot;&gt;Janki Method: More Than Just A Memory Aid&lt;/h2&gt;
&lt;p&gt;My initial goal with using Anki to learn was to stop myself from forgetting, and Anki delivered on this promise. What I wasn&amp;#8217;t expecting was the secondary advantages that emerged through long term daily use.&lt;/p&gt;
&lt;h2&gt;Advantage 1: Program Faster&lt;/h2&gt;
&lt;p&gt;Knowing thousands of commands saves time otherwise spent looking up reference materials. You instantly recall previous solutions when faced with a problem, and dozen of possibilities spring to mind when architecting a system. You will read other people&amp;#8217;s code rapidly, confident in your understanding. The closest analogy is fluency in a natural language. You will speak code.&lt;/p&gt;
&lt;p&gt;Most of the time I spend programming is spent debugging, that is fixing errors in your code or in the code of other programmers. This is where a deep knowledge of the platform will speed you up the most. Debugging consists chiefly of gathering information. What was the system supposed to do? What data was in the system when we saw the error? What could have went wrong? Frequently a single delinquent line of code can be the cause of a bug that takes down an entire site. The hard part is figuring out which of the thousands of lines of logic caused the issue.&lt;/p&gt;
&lt;p&gt;Let’s take an example. Say your program uses 100 functions and 70 of these are built into the language. That means that there were 30 custom defined functions. If you know with confidence the inputs and outputs of the 70 built-in functions, then debugging is simplified, since you will only need to figure out how the remaining 30 custom functions work.  Considering that custom functions are themselves defined in terms of built-ins, this task should not take too long either. Total certainty about the syntax, inputs, outputs, and uses of the built-in functions lets you quickly isolate unknowns and bring the bug to surface.&lt;/p&gt;
&lt;p&gt;Brainstorming ability is improved through &lt;strong&gt;Janki Method.&lt;/strong&gt; Deep knowledge in mind means you can try out alternatives on paper rapidly and so increase your chances of coming across a cheeky non-obvious solution to your problem.&lt;/p&gt;
&lt;p&gt;You might argue that you will get the same speed boost with knowledge earned through experience. That is true, but this argument misses the point. Janki enables you to gain that same knowledge faster, and retain it for longer. If you’ve ever forgotten how to do something after leaving it aside for a few months, then Anki is for you.&lt;/p&gt;
&lt;h2&gt;Advantage 2: Chunking&lt;/h2&gt;
&lt;p&gt;Skill in a technical field is the product of your intelligence and your knowledge.  Weakness in one can be overshadowed by strength in another. Bright yet inexperienced can perform on par with dull yet experienced.&lt;/p&gt;
&lt;p&gt;This point is best illustrated by example. Let’s multiply 130 by 30 using two approaches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Approach 1&lt;/strong&gt;: You know that multiplication is repeated addition, and so the problem becomes 130  + 130 + 130&amp;#8230; and so on. Applying the rules of addition you arrive at 3900 &amp;#8211; eventually. Let’s call intelligence your ability to carry out these individual calculations quickly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Approach 2&lt;/strong&gt;: Perhaps you remember from your multiplication tables in school that 13 X 3 is 39. You might also remember that the commutative and associative properties of multiplication let you simplify 130 X 30 to 10 X 13 X 3 X 10 and finally to 39 X 100, which can be calculated trivially as 3900. Your intelligence, or speed of addition here, is irrelevant since domain knowledge let you simplify the problem dramatically.&lt;/p&gt;
&lt;p&gt;In approach 1, the problem was labour intensive because you did not use knowledge to ease your calculation. This wasn’t the case in approach 2, where you reasoned using higher order chunks of knowledge, so solving an otherwise lengthy problem with ease. The application of remembered chunks of knowledge to problems at hand is called &lt;strong&gt;chunking&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you remember the answer to a question, you have no need to deduce it in the moment, and so your mind is free to deduce more abstract concepts. This is the value of chunking.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Janki Method&lt;/strong&gt; encourages chunking. This was an unexpected benefit, yet ultimately the most useful to me. After six months of daily application you will reason about programming concepts using mental shortcuts equivalent to those used to simplify the multiplication problem in approach 2. Maximize chunking by adding increasingly abstract rules and concepts to your decks, and making an effort to draw on these ideas when solving problems.&lt;/p&gt;
&lt;h2&gt;Advantage 3:  Searchable Archive of All Your Programming Knowledge&lt;/h2&gt;
&lt;p&gt;Has your computer ever spat out an error message and, although you remember seeing it before, you don&amp;#8217;t remember how to fix it? Before I started &lt;strong&gt;Janki Method&lt;/strong&gt; this would happened to me lots.&lt;/p&gt;
&lt;p&gt;The first time I saw the issue I would spend half a day solving the problem.  Six months later the problem would happen again, perhaps in a slightly different form. Even though I was vaguely aware of having seen it before, I&amp;#8217;d forgotten how to fix it.&lt;/p&gt;
&lt;p&gt;This felt wasteful and I didn&amp;#8217;t like it. I don&amp;#8217;t like having to solve the same problem twice. &lt;strong&gt;Janki Method&lt;/strong&gt; helps prevent this from happening..&lt;/p&gt;
&lt;p&gt;Anki has a search feature that finds all matching cards in your deck. You can even filter by date or tag. For example you might search through cards containing the word &amp;#8220;ssh&amp;#8221; created more than 6 months ago and tagged with ‘deployment’.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/janki/search.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;After solving a bug you should always add some cards to your deck containing the knowledge needed to prevent that bug from occurring again. Better yet, abstract one level and add cards containing the knowledge needed to prevent that class of bugs. Now, whenever you are faced with a bug the second time, all you need to do is search your archives.&lt;/p&gt;
&lt;h2&gt;Advantage 4:  Not Reinventing The Wheel&lt;/h2&gt;
&lt;p&gt;Modern programming languages have many algorithms built in, or easily included as parts of a readily available core library. This is especially true of high-level languages such as Ruby, and Python. You want to sort an array? Array#sort does the trick.&lt;/p&gt;
&lt;p&gt;If you didn’t know the sort algorithm was built into the language, then you might write your own in its place. When you do so you risk making mistakes and missing out on low level optimizations. Furthermore you alienating future users of your code, who might think there was a reason other than ignorance for why you wrote a custom sort algorithm instead of using the one built into the language.&lt;/p&gt;
&lt;p&gt;By filling your deck with built-ins from your chosen languages you will be less likely to accidentally implement existing features in a confusing, half-assed, and bug-prone way.&lt;/p&gt;
&lt;h2 class=&quot;section-title&quot;&gt;Appendix&lt;/h2&gt;
&lt;h2&gt;Should I Download Other People&amp;#8217;s Decks?&lt;/h2&gt;
&lt;p&gt;Anki has an online searchable database of other people&amp;#8217;s shared decks. Although there are not many decks for computer science, you might be able to find some and piece these together as the basis for your deck.&lt;/p&gt;
&lt;p&gt;Be careful with this. You might add facts to your deck that are of no use to you, and you may end up reviewing facts that you do not fully understand, thus building a poor foundation for future knowledge.&lt;/p&gt;
&lt;p&gt;Ideally you should build your own decks from scratch, drawing from your programming experiences; your readings of other people’s code, textbooks; viewing educational screen casts; and reviewing past mistakes and previous projects. By creating your decks in this way, you keep them filled with well-understood real world contextual knowledge, phrased and categorized in a way that makes sense to you.&lt;/p&gt;
&lt;p&gt;If you are going to use other people&amp;#8217;s decks make sure you understand every card you learn. Be sure to try the code out when you first see it; this takes more discipline that you might have. Make sure you trust the author of the deck &amp;#8211; you don&amp;#8217;t want to learn incorrect or dated knowledge, and sadly most of the decks freely available are abysmal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I have a deck with close to 6000 cards which focuses on the Ruby on Rails technology stack&lt;/strong&gt;, including cards on Ruby and Rails 3.1, the &lt;span class=&quot;caps&quot;&gt;HTTP&lt;/span&gt; protocol, the Unix command line, Git, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, JavaScript, &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, Rspec, Capybara, &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;, Coffeescript, jQuery, coffeescript, sass, deployment, design patterns, regular expressions, &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;, refactoring, and algorithms. The knowledge is cleanly tagged, nicely formatted and up to date. It&amp;#8217;s everything I&amp;#8217;ve needed to build, manage and deploy a variety of web apps. I&amp;#8217;m considering cleaning it up for public consumption and releasing it. Since this would be a lot of work on my behalf I&amp;#8217;d want to be assured of public demand first. &lt;strong&gt;If you are interested in downloading my deck then tell me by sending the message &amp;#8220;i-want-your-decks&amp;#8221; to (&lt;a href=&quot;http://www.twitter.com/jackkinsella&quot;&gt;@jackkinsella&lt;/a&gt;) on Twitter.&lt;/strong&gt; If I get enough interest I&amp;#8217;ll release them and tell you when they are available.&lt;/p&gt;
&lt;h2&gt;What Knowledge Belongs in my Decks and What Doesn’t?&lt;/h2&gt;
&lt;p&gt;When I first began &lt;strong&gt;Janki Method&lt;/strong&gt; I was over-zealous in my addition of facts to my decks. In particular, I added stacks of cards for third party code libraries. This turned out to be wasteful,  seeing as I rarely used this knowledge. Technology moves rapidly, and today’s in-vogue libraries become tomorrow’s baggage from the past. I ended up deleting many of these cards after having wastefully committed them to long-term memory.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s not always easy to distinguish between knowledge worth keeping long term and knowledge only needed short term To help me with the decision I came up with this schema:&lt;/p&gt;
&lt;p&gt;Only enter a card into your decks if one of the following conditions is met:&lt;/p&gt;
&lt;p&gt;a) The fact contains general wisdom about computer science (refactoring, regular expressions, object orientated programming, memory issues and so on).&lt;/p&gt;
&lt;p&gt;b) The fact relates to a major technology that has been around for a long time and is probably here to stay (Linux, Ruby, Javascript, &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, git, &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;c) The fact, while part of a library that is likely to change, is something I use everyday and something I foresee using for some time. Bonus points if the technology is in high demand, since this equates to higher consulting rates. (Rails, jQuery).&lt;/p&gt;
&lt;h2&gt;What are the main keyboard shortcuts I need to know?&lt;/h2&gt;
&lt;p&gt;You will be reviewing your cards everyday so it helps to small time savings here quickly compound. Keyboard shortcuts are crucial.&lt;/p&gt;
&lt;p&gt;Press &lt;strong&gt;Enter&lt;/strong&gt; to reveal answers and then evaluate your response with the keys &lt;strong&gt;0&lt;/strong&gt;,&lt;strong&gt;1&lt;/strong&gt;,&lt;strong&gt;2&lt;/strong&gt; or &lt;strong&gt;3&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Command + Backspace&lt;/strong&gt; deletes a card. Use this for troublesome/incorrect/out of date cards.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Command + E&lt;/strong&gt; lets you edit a card and then &lt;strong&gt;Tab&lt;/strong&gt; moves the cursor between the question and answer panes.&lt;/p&gt;
&lt;h2 class=&quot;section-title&quot;&gt;The Janki challenge&lt;/h2&gt;
&lt;p&gt;Want to learn to program and start building powerful apps? Then take the Janki challenge. Download Anki (link below), pick a programming project, and publicly announce to your friends that you’ve committed to learn to program.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Why public commitment? Public commitment creates social pressure that pushes you to honour your promises to the world. This pressure will see you through the difficult first stages where you will be most tempted to give up.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I believe that if you follow the system exactly as described above, you will learn to program significantly more quickly than you would using any other approach other than one-to-one tutoring.&lt;/p&gt;
&lt;h2 class=&quot;section-title&quot;&gt;Further Reading&lt;/h2&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://ankisrs.net/&quot;&gt;Anki &amp;#8211; Available for Free Download&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.supermemo.com/articles/20rules.htm&quot;&gt;20 Rules for Formulating Knowledge in Learning&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.wired.com/medtech/health/magazine/16-05/ff_wozniak?currentPage=all&quot;&gt;Want to Remember Everything You&amp;#8217;ll Ever Learn? Surrender to This Algorithm&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.supermemo.com/articles/genius.htm&quot;&gt;Genius and Creativity&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;captioned-image&quot;&gt;
&lt;p&gt;&lt;img src='/images/janki/jack-kinsella.jpg'&gt;&lt;br /&gt;
&lt;p&gt;My Jankiest Face&lt;/p&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;h2 class=&quot;section-title&quot;&gt;In San Francisco? Let’s hang out.&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;m visiting San Francisco during December 2011, so get in touch if you’d like to meet for lunch/coffee/beer. I’m looking to take on new consulting projects, or just to have a friendly chat with local techies about programming, entrepreneurship, making money online, and all the usual suspects. Get in touch; I want to meet you.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Why Bother With Cucumber Testing?</title>
   <link href="http://www.jackkinsella.ie/2011/09/26/why-bother-with-cucumber-testing.html"/>
   <updated>2011-09-26T00:00:00-07:00</updated>
   <id>http://tom.preston-werner.com/2011/09/26/why-bother-with-cucumber-testing</id>
   <content type="html">&lt;p&gt;I recently heard an account of a web development project from both the point of view of the consultancy doing the work and the client. A member of the consultancy told me how they educated a technologically backward client about agile processes. Although this might be tedious for the client initially, with time the client would appreciate their wisdom. Glowing business referrals would follow forever more.&lt;/p&gt;
&lt;p&gt;A few days later I bumped into the client:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;[X] were a nightmare to deal with. They wouldn&amp;#8217;t let me have what I wanted, and they wasted my time arguing over petty details. Although they did the job well, they had no business sense. I can’t see them lasting much longer.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The consultancy screwed up: Amongst other things, they pushed the client to use a process that wasn&amp;#8217;t appropriate. &lt;strong&gt;In particular, they gave the client Cucumber feature files to read and approve, even though the client didn&amp;#8217;t give a damn.&lt;/strong&gt; In the client’s words “all we wanted was a website”. (It was actually a web app but most non-technical people don’t draw a distinction). The client just wanted it “to work”.&lt;/p&gt;
&lt;h2&gt;Imagine You Are The Client&lt;/h2&gt;
&lt;p&gt;Step out of your programmer skin for a moment and pretend you are a busy business owner while you read the following:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;gherkin&quot;&gt;&lt;span class=&quot;k&quot;&gt;Feature:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; In order to let customers organise their information across themes on various pages. &lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;         As an administrator of a micro-site&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;         I want to be able to add subpages&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;Scenario:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; Adding a subpage&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;  Given &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I am logged in&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  Given[sic] a micro-site with a home page&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;When &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I press &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Add subpage&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;And &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I fill in &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Title&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot; with &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Gallery&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;And &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I press &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Then &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I should see a document called &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Gallery&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Scenario, but not feature description taken from &lt;a href=&quot;http://elabs.se/blog/15-you-re-cuking-it-wrong&quot;&gt;You&amp;#8217;re Cuking It Wrong&lt;/a&gt;. (Note that Jonas doesn&amp;#8217;t give his clients Cukes to read.)&lt;/p&gt;
&lt;p&gt;According to Jonas Nicklas at E-labs, the above is an example of acceptable Cucumber style, written in the language of stake-holders. As a past consumer of development services, I have to disagree with him. The appropriate level of detail here is this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;gherkin&quot;&gt;&lt;span class=&quot;nf&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;I &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;can add subpages to my micro-site.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Any more is superfluous. If it takes you ten lines to communicate the idea of adding subpages, then you&amp;#8217;ve wasted my time. I’m not alone in thinking this. &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt; expert &lt;a href=&quot;http://sirenian.livejournal.com/71439.html&quot;&gt;Elizabeth Keogh&lt;/a&gt; tells us:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;If your scenario starts with &amp;#8216;When the user enters ‘Smurf’ into ‘Search’ text box…&amp;#8217; then that’s far too low-level. However, even “When the user adds ‘Smurf’ to his basket, then goes to the checkout, then pays for the goods” is also too low-level. You’re looking for something like, &amp;#8216;When the user buys a Smurf.&amp;#8217;&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you take this view, then the overwhelming majority of the Rails community have been using Cucumber incorrectly. Despite believing otherwise, most programmers never wrote a single acceptance test; instead they wrote integration tests using the Cucumber syntax.&lt;/p&gt;
&lt;p&gt;This is a damning claim and so I offer evidence. In my experiences both as a Ruby contractor and as an employer of programmers, most feature files I’ve seen are composed of the web steps included with Cucumber by default. These web steps are integration tests in disguise. Cucumber steps such as &amp;#8220;When I fill in &amp;#8216;search&amp;#8217; with &amp;#8216;Smurf&amp;#8217;&amp;#8221; are rampant in the Rails community, despite their position at the most fault-worthy level in Elizabeth Keogh’s schema.&lt;/p&gt;
&lt;p&gt;My own anecotal experience isn&amp;#8217;t enough so I did some research. I browsed through the feature files in six major open source Rails projects, including Spree, Radiant and Diaspora. All bar one, Tracks, wrote their feature files near exclusively in web steps. In effect they wrote integration tests using the Cucumber syntax.&lt;/p&gt;
&lt;h2&gt;The Make-Believe Analyst&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s consider the above feature file again, imagining that you are the client. You run a business and so are conscious of costs. You might reasonably ask what’s with all this ‘in order to’ stuff? Why is this developer playing make-believe analyst? Doesn’t he know that you&amp;#8217;ve already communicated that you&amp;#8217;ve determined the business value when you approved development? And, most importantly of all, is the developer charging you for this work?&lt;/p&gt;
&lt;p&gt;The Cucumber way says you sit with your client and determine, feature by feature, the business value that each piece of functionality serves. That&amp;#8217;s cool, but it isn’t a realistic job description for many programmers.  High level analysts and consultants might sometimes do this, but the likelihood is that you aren’t acting as a high level consultant or analyst on your current project, and so Cucumber is inappropriate. Not only this, but using Cucumber is downright wasteful considering its cost.&lt;/p&gt;
&lt;h2&gt;The Cost of Using Cucumber&lt;/h2&gt;
&lt;h3&gt;1. Cucumber breaks text editors&lt;/h3&gt;
&lt;p&gt;Text editors, like &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, multiply productivity. Auto-completion eases the use and reuse of descriptive method names. Compilation checks prior to saving catch syntax errors before they cause harm. The editor’s ability to understand the signature of a method makes tasks such as finding method definitions and uses simple.&lt;/p&gt;
&lt;p&gt;Cucumber&amp;#8217;s steps are method names written using the Gherkin syntax, and this unique syntax breaks text editors. Steps contain white space, include their parameters at non-standard locations (When “john@gmail.com” has “4” unsent messages), and use regular expressions for pattern dispatch (&amp;#8220;and|or&amp;#8221;). Text editors are not adapted to deal with this, and so auto-complete, search and many other features break, damaging productivity.&lt;/p&gt;
&lt;h3&gt;2. Cucumber Requires Maintenance of a Second Testing Environment&lt;/h3&gt;
&lt;p&gt;Anyone thinking of using Cucumber for acceptance tests most likely already unit tests using something like Test::Unit or Rspec. When a project’s complexity grows, we organise test suites by placing shared test code into helper methods and eventually into modules shared across many test files. We also categorise tests using tagging systems, use tools like Spork to speed up test startup time, and use watchr or autotest to run tests automatically. We add gems to the test environment to make use of advanced helper methods that freeze time, open up emails, or fake web requests.&lt;/p&gt;
&lt;p&gt;Cucumber doesn&amp;#8217;t like to share. It does not pick up existing test configurations or helper methods. Our taxonomy of tags carries no weight and so we must mirror our existing setup in our new Cucumber world. If we are undisciplined about refactoring we might duplicate code, denormalizing our code base. Even if we are disciplined, we will, at the very least, increase the complexity of our project and thus the scope for error. The parallel worlds of Cucumber and our unit tests then need to be maintained, and the creators of testing gems must now care for two masters. Cucumber takes another toll on the community’s productivity.&lt;/p&gt;
&lt;h3&gt;3. Cucumber&amp;#8217;s Routing Causes Cognitive Strain&lt;/h3&gt;
&lt;p&gt;Cognitive strain refers to the total weight of facts and rules we must hold in our minds to be productive using a technology. Rails imposes a high cognitive strain. When I began using it I faced a period of difficulty as I untangled the labyrinthine naming patterns of routes, the pluralisation conventions, and the subtle distinctions between various ActiveRecord::Base persistence methods. I’m not saying that cognitive strain is a bad thing; it is often a necessity in powerful tools. I am saying that cognitive strain must be justified.&lt;/p&gt;
&lt;p&gt;In Cucumber steps, the mention of a specific web page, for example &amp;#8220;the login page&amp;#8221;, requires us to map this stake-holder description to a url helper method our app understands.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#features/support/paths.rb&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; /the login page/&lt;/span&gt;  
       &lt;span class=&quot;n&quot;&gt;login_path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The Rails routing system is complex: in &lt;em&gt;The Rails Way&lt;/em&gt; Obie Fernandez suggested that you could squeeze everyone who understands it into one taxi. Cucumber adds an abstraction layer over this already complex system, and this leads to slower development and increased error on larger projects.&lt;/p&gt;
&lt;p&gt;A problem I faced when adding new features was that I would unintentionally describe paths using differing natural language descriptions. Perhaps I&amp;#8217;d call &amp;#8220;the login page&amp;#8221; the &amp;#8220;the sign in page&amp;#8221; one day, and &amp;#8220;the log in page&amp;#8221; another. When I did this Cucumber complained that it could not find the permuted path name, and so I had to look inside the paths.rb file to remind myself of my previous phrasing. That&amp;#8217;s a lot of remembering, and a lot of room for error and slowdown.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve experimented with removing the paths.rb file and writing logic that automatically determines the route based on humanized url helpers. This leads to unacceptable step definitions such as &amp;#8220;And then I am on the new user session page&amp;#8221;. This is far too close to implementation language to be understandable to the average stakeholder, and so this option must be avoided if we&amp;#8217;d like to use Cucumber in the way it was intended.&lt;/p&gt;
&lt;h3&gt;4. Cucumber&amp;#8217;s Organisation Defaults Are Impractical&lt;/h3&gt;
&lt;p&gt;My favorite feature of Rails is one of its simplest: everything has a place. Mailers go in one folder, models go in another and configurations go somewhere else. Presuming that a project sticks to convention, you can find the source code for any function effortlessly. This brings enormous productivity advantages, especially on projects you inherit from other programmers.&lt;/p&gt;
&lt;p&gt;Cucumber asks you to create step definitions for any custom steps you use. The convention is to keep these steps in a file {feature_name}_steps.rb. This convention makes sense on tiny projects, and step definitions are easily found. Problems start once you need to reuse step definitions across many features and you want to keep code &lt;span class=&quot;caps&quot;&gt;DRY&lt;/span&gt;. Two things typically happen:&lt;/p&gt;
&lt;p&gt;1)	If you’ve got a good memory you find the old step definition and use that method again in your new feature. This can be a terrible move. The shared helper’s presence in promote_post_feature_steps.rb file suggests exclusive connection with that feature. If you later remove the promote_posts feature file you will probably remove its step definition file too, having forgotten that it contained global step definitions. Ideally you should have extracted these shared step definitions to a global step definition file, but realistically this doesn’t always happen. We&amp;#8217;ve all got deadlines.&lt;/p&gt;
&lt;p&gt;2)	If you don’t have a good memory, or it has been a long time since you last visited the project, you might have forgotten that you previously wrote a step definition for promoting a post. Alternatively you might never have created a step definition but another programmer had done so without you knowing. You write a fresh step definition in taxon_steps.rb, but now your code is no longer &lt;span class=&quot;caps&quot;&gt;DRY&lt;/span&gt;. At a later date you might be refactoring the promotion logic and make the changes in promote_post_feature_steps.rb, and then assume you had finished refactoring. The taxon_steps.rb now contains an out of date version of the logic for this step, and this will lead to confusing test failures, since you have no good reason to suspect an issue with the recently refactored promotion logic. Cucumber’s default way of organising features sets you up for these difficulties, and it takes of discipine to avoid them.&lt;/p&gt;
&lt;h3&gt;5. Increased Wordiness&lt;/h3&gt;
&lt;p&gt;Do you consider one of Ruby’s advantages its brevity compared to other languages such as Java? Do you prefer Sass, Coffeescript and Slim to &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt;, Javascript and &lt;span class=&quot;caps&quot;&gt;ERB&lt;/span&gt; for the same reason? Then why do you persist in using Cucumber?&lt;/p&gt;
&lt;p&gt;Method names in Cucumber need twice as many characters as their plainer Capybara equivalents. Compare:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;gherkin&quot;&gt;&lt;span class=&quot;k&quot;&gt;Given &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I am on the home page &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#27 characters&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;visit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root_url&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#14 characters&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Increased wordiness reduces expressiveness and power, and introduces error since more characters means more places a typo can appear.&lt;/p&gt;
&lt;h4&gt;6. Cucumber Syntactically Discourages Code Reuse&lt;/h4&gt;
&lt;p&gt;Cucumber users tend to write their step definition in terms of other step definitions.  The library creators have implicitly encouraged this by creating simple means for doing so. Here’s an example:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;gherkin&quot;&gt;&lt;span class=&quot;k&quot;&gt;When &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;/^I toggle the full sample on the “(^”.*)” product/ do |product_name|&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  steps %Q{&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;When &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I am on the last upload page for “&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#{product_name}”&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;And &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I follow &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;full_samples&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;And &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I press &amp;quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;toggle_full_sample&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;When &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;I refresh the page&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;  }&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This is an abomination, albeit one that is understandable. A developer wants his code to remain &lt;span class=&quot;caps&quot;&gt;DRY&lt;/span&gt; but he doesn&amp;#8217;t want the added hassle of encapsulating the step definitions in Ruby methods. So, he reuses his step definitions.&lt;/p&gt;
&lt;p&gt;But consider this: When you are inside a step definition you are exclusively in the domain of the programmer. The stake-holder never reads this. With this in mind, wouldn’t it be advantageous to use the brevity, precision, composability, editor support and abstraction tools of the full Ruby programming language? Using Ruby, you will be able to do things like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;no&quot;&gt;When&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; /^I toggle the full sample on the “(^”.*)” product/&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;product_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;admin&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;feature_latest_upload&lt;/span&gt; 
        &lt;span class=&quot;n&quot;&gt;refresh_page&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;should_see&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;features&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The reuse of step definitions within other step definitions, and the composition of higher level steps using the web steps included with Cucumber, are, in my opinion, the main reasons why so many companies attempt integration tests only to abandon the effort within a few months.  The tests become too difficult to maintain and get of sync. The solution to this pain point isn’t simple, but the most sensible course involves use of more powerful tools of abstraction – such as the full Ruby programming language over awkward step definitions.&lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Cucumber has its uses, principally as a high level analysis tool on large, polyglot projects. That said, few programmers work in this kind of position, and acceptance tests beyond a list of the method names of regular integration tests seems wasteful. Cucumber, as used by the majority of Rails programmers, is no more than a clumsy wrapper over basic integration tests. The differences are not just cosmetic: Cucumber&amp;#8217;s syntax is costly, both to the programmer and to the client, whose time and money are wasted. Furthermore, the use of Cucumber in open source software intended for technical users and its use in solopreneur efforts is downright ridiculous. Nevertheless, programmers continue to use Cucumber inappropriately.&lt;/p&gt;
&lt;p&gt;Why not admit to yourself that you don&amp;#8217;t do acceptance testing and that you do not need it in your projects? Swap Cucumber for pure integration tests using Capybara, and you&amp;#8217;ll be surprised by how much more productive you can be.&lt;/p&gt;</content>
 </entry>
 
 <entry>
   <title>Textmate to VIM</title>
   <link href="http://www.jackkinsella.ie/2011/09/05/textmate-to-vim.html"/>
   <updated>2011-09-05T00:00:00-07:00</updated>
   <id>http://tom.preston-werner.com/2011/09/05/textmate-to-vim</id>
   <content type="html">&lt;p&gt;When I switched from Textmate to &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; I felt like a tourist lost on a Japanese subway without a guide, translator or hope. I was unable to find in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; the features I&amp;#8217;d come to love and rely on in Textmate. I yearned for ⌘ + T to summon my models, a project drawer to manage my files, and snippets to save my fingers.&lt;/p&gt;
&lt;p&gt;Instead of accommodating my needs, &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; sat firm and unresponsive, save for a judgemental beep. Even though I was supposed to go cold turkey on Textmate, I met her by night for a guilty after-hours edit.&lt;/p&gt;
&lt;p&gt;With time I learned to mimic nearly every Textmate feature in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;, and then some. This guide isn&amp;#8217;t about the powerful functionality &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; has over-and-above Textmate; you&amp;#8217;ll figure this out with time. This guide is to help you do in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; what you already can using Textmate, only with considerably less pain than I underwent.&lt;/p&gt;
&lt;p&gt;This guide makes a few assumptions:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;You are using a Mac.&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;ve installed Mac &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;. The easiest way is using Home Brew. &lt;br /&gt;
&lt;code&gt;brew install macvim&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;ve installed &lt;a href=&quot;https://github.com/carlhuda/janus&quot;&gt;Janus&lt;/a&gt;, the community maintained &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; distro with plugins and configurations useful to Rails programmers accustomed to Textmate.&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;ve created a ~/.vimrc.local file (for core &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; configurations), ~/.gvimrc.local (for configuring the graphics in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;) and ~/.janus.rake (for adding or removing plugins in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;). See my &lt;a href=&quot;https://github.com/jackkinsella/dotfiles/tree/&quot;&gt;dotfiles&lt;/a&gt; for some commented examples. Better yet, use them as sensible defaults.&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;ve already learned the basics of &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;. If you haven&amp;#8217;t type vimtutor in your terminal for a 20 minute tutorial. Advanced training can be found be referring to the &lt;a href=&quot;#vim_training_resources&quot;&gt;vim training resources&lt;/a&gt; below.&lt;/li&gt;
	&lt;li&gt;You were a power user of Textmate.&lt;/li&gt;
	&lt;li&gt;You are a Rails programmer switching from Textmate to &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;. About 30% of this guide is Rails specific.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;This guide may only be reproduced with the express permission of Jack Kinsella &amp;#8211; &lt;a href=&quot;/rails-developer-london.html&quot;&gt;Rails Developer, London&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Some Preliminary Notes (Do Not Skip)&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Command &lt;/td&gt;
		&lt;td&gt; Shortcut in Textmate &lt;/td&gt;
		&lt;td&gt; Shortcut in Vim&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;ul&gt;
	&lt;li&gt;In general the keyboard shortcuts in Textmate require you to press the keys at the same time. Below, this is symbolised by a +. VIM&amp;#8217;s shortcuts, by contrast, typically require you to press the keys in quick succession, rather than at the same time. If you see &amp;#8216;dd&amp;#8217; this means type d twice.&lt;/li&gt;
	&lt;li&gt;Whilst commands in Textmate are &lt;em&gt;case insensitive&lt;/em&gt;, or rather the shift key is specified in the commands below, the commands in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; are &lt;em&gt;case sensitive&lt;/em&gt;. If I tell you to type Y then typing y will not suffice.&lt;/li&gt;
	&lt;li&gt;Unless otherwise specified, all the &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; commands assume you are in normal mode, the mode where you cannot type text into the file.&lt;/li&gt;
	&lt;li&gt;If I instruct you to add something to your vimrc.local or gvimrc.local files you will need to type :source ~/.vimrc.local or :source .gvimrc.local to reload &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; with your changes.&lt;/li&gt;
	&lt;li&gt;If I instruct you to add code to your .janus.rake file, you must cd into your ~/.vim directory and run rake for these changes to be installed.&lt;/li&gt;
	&lt;li&gt;Regular expressions in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; differ from those in Textmate, and these are outside the scope of this guide. 90% of these differences will be alleviated if you add this to your .vimrc.local:&lt;br /&gt;
&lt;code&gt;nnoremap / /\v&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;vnoremap / /\v&lt;/code&gt;&lt;br /&gt;
&lt;em&gt;This automaticaly prefixes your search commands with \v (Technically, the commands map the key /, symbolising search, to /\v, meaning search with &amp;#8216;very magic&amp;#8217; regex syntax. There are two entries since the remapping happens in two modes.). &amp;#8216;Very magic&amp;#8217; regex syntax means that all &lt;span class=&quot;caps&quot;&gt;ASCII&lt;/span&gt; characters except &amp;#8216;0&amp;#8217;-&amp;#8216;9&amp;#8217;, &amp;#8216;a&amp;#8217;-&amp;#8216;z&amp;#8217;, &amp;#8216;A&amp;#8217;-&amp;#8216;Z&amp;#8217; and &amp;#8216;_&amp;#8217; have a special meaning.  Without this you would need to escape many characters which are standard regex syntax in, say, Ruby.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Opening, Closing and Creating Files&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Open a file&lt;/td&gt;
		&lt;td&gt; ⌘ + 0 &lt;/td&gt;
		&lt;td&gt; :e &lt;span class=&quot;caps&quot;&gt;FILENAME&lt;/span&gt; &lt;br /&gt;
&lt;em&gt;Use Tab completion after typing the first few letters&lt;/em&gt; &lt;br /&gt;
&lt;em&gt;You may need to save your current file first&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Create new file&lt;/td&gt;
		&lt;td&gt; File &amp;gt; new &lt;/td&gt;
		&lt;td&gt; ⌘ + T (new tab) &lt;br /&gt;
&lt;em&gt;You will be in a new file on a separate tab. Type something and then save with:&lt;/em&gt;&lt;br /&gt;
:w newfilename &lt;br /&gt;
:e new_filename&lt;br /&gt;
&lt;em&gt;Opens a new file in the current window&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Quit&lt;/td&gt;
		&lt;td&gt; ⌘ + q &lt;/td&gt;
		&lt;td&gt; :q &lt;br /&gt;
&lt;em&gt;This throws an error if you have not saved. use :wq to save and quit or :q! to quit without saving&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Open project from command line&lt;/td&gt;
		&lt;td&gt; [cd to folder] mate . &lt;/td&gt;
		&lt;td&gt; [cd to folder] mvim . &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Saving Files&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Save file&lt;/td&gt;
		&lt;td&gt; ⌘ + S &lt;/td&gt;
		&lt;td&gt; :w &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Save file as&lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + S &lt;/td&gt;
		&lt;td&gt; :w &lt;span class=&quot;caps&quot;&gt;NEWFILENAME&lt;/span&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Undo / Redo&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Undo&lt;/td&gt;
		&lt;td&gt;⌘ + Z &lt;/td&gt;
		&lt;td&gt; u &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Redo&lt;/td&gt;
		&lt;td&gt; ⇧ + ⌘ + Z &lt;/td&gt;
		&lt;td&gt; ⌃ + R &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;File Renaming&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Rename a file&lt;/td&gt;
		&lt;td&gt; Focus on the project drawer and select a file. Press spacebar. Type a new name. &lt;/td&gt;
		&lt;td&gt; Start by &lt;a href=&quot;#nerd_tree&quot;&gt;focusing on the NERDTree&lt;/a&gt;. Select the file you wish to rename (however you want: e.g. with a search or plain old jklh). Type &amp;#8216;m&amp;#8217; to bring up a menu. Type &amp;#8216;m&amp;#8217; again to chose to modify the file name. Type the new name of file and press enter. &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2 id=&quot;nerd_tree&quot;&gt;Project Drawer/ NERDTree&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Focus on project drawer&lt;/td&gt;
		&lt;td&gt; ⌃ + &lt;Tab&gt; &lt;/td&gt;
		&lt;td&gt; &lt;a href=&quot;#switch_tabs&quot;&gt;Switch tabs until selected&lt;/a&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Close/Open project drawer&lt;/td&gt;
		&lt;td&gt; ⌃ + ⌥ + ⌘ + D &lt;/td&gt;
		&lt;td&gt;\n&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Change size of project drawer&lt;/td&gt;
		&lt;td&gt; Use mouse to adjust size &lt;/td&gt;
		&lt;td&gt; [add this to your .vimrc] let NERDTreeWinSize=16 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Create new in Project Drawer &lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + N &lt;/td&gt;
		&lt;td&gt; Select Project Drawer. Highlight parent folder you&amp;#8217;d like file to appear in. Type m the choose a from select menu and type desired filename &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Delete a file&lt;/td&gt;
		&lt;td&gt; Click on file and select &amp;#8220;remove file&amp;#8221; &lt;/td&gt;
		&lt;td&gt; Highlight undesired file file in Project Drawer. Type m then choose d from drop down menu.&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Opening a sub-folder&lt;/td&gt;
		&lt;td&gt; &lt;/td&gt;
		&lt;td&gt;Enter to open/close a directory&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Refresh project tree to reflect newly added files&lt;/td&gt;
		&lt;td&gt;Automatic&lt;/td&gt;
		&lt;td&gt;Nearly always automatic. Otherwise press r&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Clipboard&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Copy&lt;/td&gt;
		&lt;td&gt; ⌘ + C&lt;/td&gt;
		&lt;td&gt; yy&lt;br /&gt;
&lt;em&gt;Copies the current selection, or, if there is no selection, the current line&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Cut&lt;/td&gt;
		&lt;td&gt; ⌘ + X &lt;/td&gt;
		&lt;td&gt; d&lt;br /&gt;
&lt;em&gt;Technically this deletes the selection, but deleting in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; saves the deleted text to a register where it can be now be pasted with p&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Paste&lt;/td&gt;
		&lt;td&gt; ⌘ + V &lt;/td&gt;
		&lt;td&gt; p&lt;br /&gt;
&lt;em&gt;Pastes below the current line&lt;/em&gt; &lt;br /&gt;
P&lt;br /&gt;
&lt;em&gt;pastes above the current line&lt;/em&gt;&lt;br /&gt;
&amp;#8220;0p&lt;br /&gt;
&lt;em&gt;this pastes the last &lt;strong&gt;explicitly copied&lt;/strong&gt; text. this is important since many commands, such as deleting text, override the paste buffer&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Paste from system clipboard&lt;/td&gt;
		&lt;td&gt; As above. &lt;/td&gt;
		&lt;td&gt; &amp;quot;*p&lt;br /&gt;
&lt;em&gt;&lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; distinguishes between its internal clipboards (buffers) and the system&amp;#8217;s clipboard.&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Clipboard history&lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + V &lt;/td&gt;
		&lt;td&gt; :reg &lt;br /&gt;
&lt;em&gt;Show a list of registers each of which can be pasted e.g. &amp;quot;8p pastes the contents of the register 8&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2 id=&quot;switch_tabs&quot;&gt;Tabs&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;New tab&lt;/td&gt;
		&lt;td&gt; Click on file in project drawer &lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + T &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Drop tab&lt;/td&gt;
		&lt;td&gt; ⌃ + w &lt;/td&gt;
		&lt;td&gt; ⌃ + w &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Switch tabs left &lt;/td&gt;
		&lt;td&gt; ⇧ + ⌘ + ←&lt;/td&gt;
		&lt;td&gt; gT &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Switch tabs right &lt;/td&gt;
		&lt;td&gt; ⇧ + ⌘ + →&lt;/td&gt;
		&lt;td&gt; gt &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to tab&lt;/td&gt;
		&lt;td&gt; ⌘[1-9] &lt;/td&gt;
		&lt;td&gt; ⌘[1-9]&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Moving Around A File&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to beginning of line&lt;/td&gt;
		&lt;td&gt; ⌃ + A &lt;/td&gt;
		&lt;td&gt; ^ &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to end of line &lt;/td&gt;
		&lt;td&gt; ⌃ + E &lt;/td&gt;
		&lt;td&gt; $ &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to top of file &lt;/td&gt;
		&lt;td&gt; ⌘ + ↑ &lt;/td&gt;
		&lt;td&gt; gg &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to bottom of file &lt;/td&gt;
		&lt;td&gt; ⌘ + ↓ &lt;/td&gt;
		&lt;td&gt; G &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Move up one line (with caret at same position)&lt;/td&gt;
		&lt;td&gt; ⌃ + P &lt;/td&gt;
		&lt;td&gt; k &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Move down one line (with caret at same position)&lt;/td&gt;
		&lt;td&gt; ⌃ + N&lt;/td&gt;
		&lt;td&gt; j&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to line 20 &lt;/td&gt;
		&lt;td&gt; ⌘ + L [type a line &amp;#8211; e.g. 20] &lt;/td&gt;
		&lt;td&gt; :20 &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Jump between words left&lt;/td&gt;
		&lt;td&gt; ⌥ + ← w &lt;/td&gt;
		&lt;td&gt; b or B &lt;br /&gt;
&lt;em&gt;Lowercase b goes back one word, where puntuation marks count as word separators. B is back one word where only spaces count as word separators.&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Jump between words right&lt;/td&gt;
		&lt;td&gt; ⌥ + →&lt;/td&gt;
		&lt;td&gt; w or W &lt;br /&gt;
&lt;em&gt;same distinction as above&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Selecting Text&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt; Begin selection &lt;/td&gt;
		&lt;td&gt; ⇧ [then use arrows to drag over desired text] &lt;/td&gt;
		&lt;td&gt; v[enters visual mode. use w to move forward one word. ) to move forward one sentence and % to move to next bracket close. also /apple to move forward to next occurrence of apple]&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Select all&lt;/td&gt;
		&lt;td&gt; ⌘ + A &lt;/td&gt;
		&lt;td&gt; ggVG &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Increase selection left one word&lt;/td&gt;
		&lt;td&gt; ⇧ + ⌥ + ← then alt + ← for each additional word&lt;/td&gt;
		&lt;td&gt; v(select)w then w for each additional word  &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Select a vertical block&lt;/td&gt;
		&lt;td&gt; ⌥ + drag mouse &lt;/td&gt;
		&lt;td&gt; ⌃ + v &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Deleting Text&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Delete line&lt;/td&gt;
		&lt;td&gt;⌘ + ⇧ + k &lt;/td&gt;
		&lt;td&gt; dd &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Delete character&lt;/td&gt;
		&lt;td&gt; Backspace &lt;em&gt;Erases character to the left of the caret&lt;/em&gt; &lt;/td&gt;
		&lt;td&gt;x &lt;br /&gt;
&lt;em&gt;Erases character under caret&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Delete selected text&lt;/td&gt;
		&lt;td&gt; Backspace &lt;/td&gt;
		&lt;td&gt; d &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Moving Text Around&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Move selected text up&lt;/td&gt;
		&lt;td&gt;⌃ + ⌘ + ↑ (or ↓)&lt;/td&gt;
		&lt;td&gt; :m 22 &lt;br /&gt;
&lt;em&gt;moves current line to line 22. Easier if line numbers are on with :set number. Alternatively :m+ or :m+N or :m-N for moving 1 or N lines up or down&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Merge current line With Next Line&lt;/td&gt;
		&lt;td&gt;⌃ + ⇧ +J &lt;/td&gt;
		&lt;td&gt; J &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Sort lines&lt;/td&gt;
		&lt;td&gt; ⌥ + ⌘ + R &amp;gt; sort in dialogue box &lt;/td&gt;
		&lt;td&gt; &lt;em&gt;Where you have previously selected text&lt;/em&gt;&lt;br /&gt;
!:sort &lt;br /&gt;
&lt;em&gt;Where you have nothing selecting and want to act on whole file&lt;/em&gt;&lt;br /&gt;
:%!sort (% is a symbol representing the whole file) &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Searching Files&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Search file downwards for &lt;span class=&quot;caps&quot;&gt;TOM&lt;/span&gt; &lt;/td&gt;
		&lt;td&gt;⌃ + S &lt;span class=&quot;caps&quot;&gt;TOM&lt;/span&gt;  &lt;/td&gt;
		&lt;td&gt; /Tom &lt;br /&gt;
&lt;em&gt;Then press they enter key and then you can press n or N repeatedly to continue searching up or down&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Search file upwards for &lt;span class=&quot;caps&quot;&gt;TOM&lt;/span&gt; &lt;/td&gt;
		&lt;td&gt; ⇧ + ⌃ + S &lt;span class=&quot;caps&quot;&gt;TOM&lt;/span&gt; &lt;/td&gt;
		&lt;td&gt; ?&lt;span class=&quot;caps&quot;&gt;TOM&lt;/span&gt; &lt;br /&gt;
&lt;em&gt;As above, n or N continue searching up or down&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Full screen &lt;/td&gt;
		&lt;td&gt;&lt;a href=&quot;https://github.com/enormego/EGOTextMateFullScreen&quot;&gt;(Lion Only)&lt;/a&gt; &lt;/td&gt;
		&lt;td&gt; ⌘ + Enter &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Search entire project &lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + F &lt;/td&gt;
		&lt;td&gt; ,a THING_SEARCHING_FOR (ack) &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Find a specific method&lt;/td&gt;
		&lt;td&gt;⌘ + ⇧ + t&lt;/td&gt;
		&lt;td&gt; /def foo &lt;br /&gt;
&lt;em&gt;then use * to cycle through instances of the method name under the caret. This will not necessarily by definition # does the same but in the oppose direction&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Replacing Text in Files and in Entire Project&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Replace all &amp;#8220;donut&amp;#8221; with &amp;#8220;eclair&amp;#8221; in file&lt;/td&gt;
		&lt;td&gt; ⌘ F &lt;br /&gt;
&lt;em&gt;Find and replace box where you select &amp;#8216;Replace All&amp;#8217;.&lt;/em&gt; &lt;/td&gt;
		&lt;td&gt; :%s/donut/eclair/g &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Replace all &amp;#8220;donut&amp;#8221; with &amp;#8220;eclair&amp;#8221; in file, ignoring case &lt;/td&gt;
		&lt;td&gt; ⌘ F&lt;br /&gt;
 &lt;em&gt;Find and replace dialogue where you then select &amp;#8216;Ignore Case&amp;#8217;and then &amp;#8216;Replace All&amp;#8217;.&lt;/em&gt; &lt;/td&gt;
		&lt;td&gt; :%s/donut/eclair/gi &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Replace all &amp;#8220;donut&amp;#8221; with &amp;#8220;eclair&amp;#8221; in file, confirming each time &lt;/td&gt;
		&lt;td&gt; ⌘ F &lt;br /&gt;
&lt;em&gt;Find and replace box where you select &amp;#8216;Replace Next&amp;#8217;.&lt;/em&gt; &lt;/td&gt;
		&lt;td&gt; :%s/donut/eclair/gc &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Replace &amp;#8220;donut&amp;#8221; with &amp;#8220;eclair&amp;#8221; in entire project&lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + F &lt;/td&gt;
		&lt;td&gt; :Ack donut[Enter]. A window pops up with all instances of the term. &lt;Tab&gt; into the ack search window. Type :bufdo %s/donut/eclair/gce. :q the ack search window once down to close it.&lt;br /&gt;
&lt;em&gt;Save current file first if &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; throws an error&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Replace &amp;#8220;donut&amp;#8221; with &amp;#8220;eclair&amp;#8221; in entire project&lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + F &lt;/td&gt;
		&lt;td&gt; ,a donut[Enter] &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Ruby On Rails&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Nearly all of this functionality is thanks to Tpope&amp;#8217;s &lt;a href=&quot;https://github.com/tpope/vim-rails&quot;&gt;Rails.vim plugin&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Call Ruby On Rails generate script &lt;/td&gt;
		&lt;td&gt; &amp;quot;⌃ + Pipe [1..8]== &lt;/td&gt;
		&lt;td&gt;:Rgenerate [controller model scaffold] Blog &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go To Last Migration&lt;/td&gt;
		&lt;td&gt; None &lt;/td&gt;
		&lt;td&gt; :Rmig  &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Run migrations&lt;/td&gt;
		&lt;td&gt; ⌃ + ⇧ + Pipe &lt;/td&gt;
		&lt;td&gt;[when in a migration] :Rake &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Switch focus to project drawer&lt;/td&gt;
		&lt;td&gt; ⌘ + ⌥ + ` (check)&lt;/td&gt;
		&lt;td&gt; ⌃ + w ⌃ + w &lt;br /&gt;
&lt;em&gt;A good key remapping is to map this onto tab by adding this to your vimrc: noremap &lt;tab&gt; &lt;C-w&gt;&lt;C-w&gt;&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Insert erb&amp;#8217;s &amp;lt;%= &lt;/td&gt;
		&lt;td&gt; ⌃ + ⇧ + . &lt;/td&gt;
		&lt;td&gt; Type text you want to surround first and place caret some inside. yss= &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Insert erb&amp;#8217;s &amp;lt;% &lt;/td&gt;
		&lt;td&gt; ⌃ + ⇧ + . &lt;/td&gt;
		&lt;td&gt; yss- &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Run unit test caret inside of &lt;/td&gt;
		&lt;td&gt; ⇧ + ⌘ + R &lt;/td&gt;
		&lt;td&gt; :.Rake &lt;br /&gt;
&lt;em&gt;. here represents the current line. You can substitute this for other lines e.g. :40Rake&lt;/em&gt; &lt;span class=&quot;caps&quot;&gt;TEST&lt;/span&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to test file (e.g. from user.rb to user_spec.rb)&lt;/td&gt;
		&lt;td&gt; ⌥ + ⇧  + ⌘ + ↓ &lt;/td&gt;
		&lt;td&gt; :A (:AV in a new split, :AT new tab)&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Find related file&lt;/td&gt;
		&lt;td&gt; ⌥ + ⌘ + ↓ &lt;/td&gt;
		&lt;td&gt; :R&lt;br /&gt;
&lt;em&gt;If typed within the Controller you&amp;#8217;ll be brought to the View corresponding to the method selected; If typed in view &amp;#8594; Controller; Migrations &amp;#8594; Next Migration; Typed in Model &amp;#8594; Schema. For something more precise see the following &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; only commands&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to related controller&lt;/td&gt;
		&lt;td&gt; ⌥ + ⇧ + ⌘ + ↓ &lt;/td&gt;
		&lt;td&gt; :Rco &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to related helper&lt;/td&gt;
		&lt;td&gt; As above &lt;/td&gt;
		&lt;td&gt; :Rhe &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to model under cursor&lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; gf [e.g. you see Pos*t.first &amp;#8594; brought to #post.rb &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to stylesheet under cursor&lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; gf [e.g. you see&amp;lt;%= stylesheet_link_tag &amp;#8216;scaf*fold&amp;#8217; %&amp;gt;&amp;#8594; brought to scaffold.css &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;View Rails logs&lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; :Rlogs &lt;br /&gt;
&lt;em&gt;:Rake logs:clear if takes too long to load&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to layout under cursor&lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; gf &lt;br /&gt;
&lt;em&gt;e.g. you see layout :print &amp;#8594; brought to #print.html.erb&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to application.rb&lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; :Renv&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to test.rb &lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; :Renv t[tab to autofill out to test]&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Go to controller from link under cursor&lt;/td&gt;
		&lt;td&gt; No equivalent&lt;/td&gt;
		&lt;td&gt; gf [e.g. you see &amp;lt;%= link_to &amp;#8220;New&amp;#8221;, new_comme*nt_path %&amp;gt; &amp;#8594; brought to #comments_controller.rb &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Create a posts controller &lt;/td&gt;
		&lt;td&gt; No equivalent &lt;/td&gt;
		&lt;td&gt;:Rco posts! &lt;br /&gt;
&lt;em&gt;Note the exclamation mark which distinguishes this create command from the find command.&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Extract to partial&lt;/td&gt;
		&lt;td&gt; [Select text] ⌃ + H &lt;/td&gt;
		&lt;td&gt; [Select text] :Rextract PARTIAL_NAME &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Indentation&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Automatically indent code beautifully on whole file &lt;/td&gt;
		&lt;td&gt; ⌥ + ⌘ + B (&lt;a href=&quot;https://github.com/mocoso/code-beautifier.tmbundle&quot;&gt;Code Beautifier Plugin&lt;/a&gt;) &lt;/td&gt;
		&lt;td&gt; gg=G &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Fix indentation on selected area &lt;/td&gt;
		&lt;td&gt; No equivalent &lt;/td&gt;
		&lt;td&gt; = &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Fix indentation on a single line &lt;/td&gt;
		&lt;td&gt; No equivalent &lt;/td&gt;
		&lt;td&gt; == &lt;br /&gt;
&lt;em&gt;Compare with the above to note a pattern. Type a command once to apply it to visually selected areas. Type it twice to apply to the current line, which need not be selected. See also d and dd, y and yy&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Indent&lt;/td&gt;
		&lt;td&gt;⌘ + [ &lt;/td&gt;
		&lt;td&gt; &amp;gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Unindent&lt;/td&gt;
		&lt;td&gt; ⌘ + ] &lt;/td&gt;
		&lt;td&gt; &amp;lt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Font Size, Line Numberings&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Bigger/Smaller Font&lt;/td&gt;
		&lt;td&gt; ⌘ +/- &lt;/td&gt;
		&lt;td&gt;  [~/gvimrc.local] set guifont=Monaco:h18 &lt;br /&gt;
&lt;em&gt;You can replace 18 here with your desired font-size&lt;/em&gt;&lt;br /&gt;
&lt;em&gt;[Note that you can try this command out by typing it into a live &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; session just by preceding it with a :, e.g. :set&amp;#8230;..&lt;/em&gt;&lt;br /&gt;
_Using ⌘ +/- in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; makes the screen scale disproportionately &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Line numbering&lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + L&lt;/td&gt;
		&lt;td&gt; :set number &lt;br /&gt;
&lt;em&gt;Turn on&lt;/em&gt;&lt;br /&gt;
:set nonumber &lt;br /&gt;
&lt;em&gt;Turn off&lt;/em&gt;. &lt;br /&gt;
&lt;em&gt;Note the symmetry between turning the number on and off, the only different being the preceded &amp;#8220;no&amp;#8221;. This is the same for all &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; set commands. As with other preferences this may be placed in vimrc.local&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Spell Checking&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Highlight incorrect spellings&lt;/td&gt;
		&lt;td&gt; ⌥ + ⌘ + ; &lt;/td&gt;
		&lt;td&gt; :set spell &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Next incorrect spelling &lt;/td&gt;
		&lt;td&gt; ⌘ + : &lt;/td&gt;
		&lt;td&gt; [Assuming you&amp;#8217;ve enabled spell checking and can see highlighter errors] ] s &lt;br /&gt;
&lt;em&gt;Go to previous spelling error with [s&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Suggest correct spelling&lt;/td&gt;
		&lt;td&gt; Double click and select best spelling &lt;/td&gt;
		&lt;td&gt; z= &lt;br /&gt;
&lt;em&gt;Then choose the correct spelling from drop down menu&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Bookmarks&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Add bookmark&lt;/td&gt;
		&lt;td&gt; ⌘ + F2 (Never worked on my mac) &lt;/td&gt;
		&lt;td&gt; m[a-z] &lt;br /&gt;
&lt;em&gt;The letter in the range refers to this bookmark&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Jump to bookmark&lt;/td&gt;
		&lt;td&gt; F2 (next) + F2 (previous) &lt;/td&gt;
		&lt;td&gt; &amp;#8217;a &lt;br /&gt;
&lt;em&gt;Where a is a bookmark previously set. Type :marks to see all bookmarks&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Uppercase/Lowercase&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Upcase selected text&lt;/td&gt;
		&lt;td&gt;⌃ + ⇧ + U&lt;/td&gt;
		&lt;td&gt; u &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Downcase selected text&lt;/td&gt;
		&lt;td&gt;⌃ + ⇧ + U&lt;/td&gt;
		&lt;td&gt; U &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Switchcase of selected text &lt;/td&gt;
		&lt;td&gt; ⌃ + g &lt;/td&gt;
		&lt;td&gt; ~ &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Titlecase current text&lt;/td&gt;
		&lt;td&gt; ⌃ + ⌥ + U &lt;/td&gt;
		&lt;td&gt; No exact equivalent &lt;br /&gt;
&lt;em&gt;To titlecase the current line you can use :s :s/\&amp;lt;\(\w\)\(\w*\)\&amp;gt;/\u\1\L\2/g&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Auto-complete&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;All of the following commands assume you are in insert mode&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Auto-complete method&lt;/td&gt;
		&lt;td&gt; ⎋ after typing first few letters&lt;/td&gt;
		&lt;td&gt; Tab after typing first few letters&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Auto-complete filename&lt;/td&gt;
		&lt;td&gt; No equivalent &lt;/td&gt;
		&lt;td&gt; ⌃ + X ⌃ + F &lt;br /&gt;
&lt;em&gt;Only fills one directory at a time so you&amp;#8217;ll need to repeat for each additional one&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Auto-complete full line of code &lt;/td&gt;
		&lt;td&gt; No equivalent &lt;/td&gt;
		&lt;td&gt; ⌃ + X + l &lt;/td&gt;
&lt;/table&gt;
&lt;h2&gt;Commenting Code&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Comment Line or Selection&lt;/td&gt;
		&lt;td&gt; ⌘ + / &lt;/td&gt;
		&lt;td&gt; ⌘ + / &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Syntax Errors&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Check for syntax errors on saving (*life saver)&lt;/td&gt;
		&lt;td&gt; &lt;a href=&quot;https://github.com/sxtxixtxcxh/validate-on-save.tmbundle&quot;&gt;Validate On Save Plugin&lt;/a&gt; &lt;/td&gt;
		&lt;td&gt; Built In &lt;br /&gt;
&lt;em&gt;A grey bar appears right of the number column with an &amp;gt; beside the error&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Auto-closing Quotes, Html Tags, Brackets.&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;All of the following commands assume you are in insert mode&lt;/em&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Add opposing bracket or quotation mark&lt;/td&gt;
		&lt;td&gt; Typing a &amp;quot; will automatically add in closing. &lt;/td&gt;
		&lt;td&gt; Add &lt;a href=&quot;https://gist.github.com/1193298&quot;&gt;this gist&lt;/a&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Close current html tag&lt;/td&gt;
		&lt;td&gt;⌘ + ⌥ + .&lt;/td&gt;
		&lt;td&gt; ⌃ + x + / &lt;em&gt;Also you have auto tag creation. To create &lt;p&gt;&lt;/p&gt; type p then  ⌃ + X Spacebar&lt;/em&gt; &lt;br /&gt;
&lt;em&gt;Assumes you have the following in your ~/.janus.rake file:&lt;br /&gt;
vim_plugin&lt;/em&gt;task &amp;#8220;ragtag&amp;#8221;, &amp;#8220;git://github.com/tpope/vim-ragtag.git&amp;#8221;&lt;br /&gt;
_ &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; Colours&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;View &lt;span class=&quot;caps&quot;&gt;CSS&lt;/span&gt; colour wheel&lt;/td&gt;
		&lt;td&gt; ⌘ + ⇧ + C &lt;/td&gt;
		&lt;td&gt; No exact equivalent.  vim_plugin_task &amp;#8220;vim-css-color&amp;#8221;, &amp;#8216;git://github.com/skammer/vim-css-color.git&amp;#8217; turns #acbdef into its correct colour&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Running Tests and Files&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Run tests for given file&lt;/td&gt;
		&lt;td&gt;⌘ + r &lt;/td&gt;
		&lt;td&gt; :Rake &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Run current file&lt;/td&gt;
		&lt;td&gt; ⌘ + R &lt;/td&gt;
		&lt;td&gt; :!ruby % &lt;br /&gt;
&lt;em&gt;Explanation: :! means execute what follows as if in shell. % expands to the current_file_name so you are executing `ruby current_file_name. This runs in a buffer in &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; making you unable to continue editing.&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Snippets&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Snippets (e.g. validates present of)&lt;/td&gt;
		&lt;td&gt; vp + &lt;span class=&quot;caps&quot;&gt;TAB&lt;/span&gt; &lt;/td&gt;
		&lt;td&gt; vp ⌃ + ] &lt;br /&gt;
&lt;em&gt;Abbreviations same as in Textmate&lt;/em&gt; &lt;br /&gt;
&lt;em&gt;Non Rails snippets not working since the latest releases of snippets plugin clashes with Command-T search plugin. I&amp;#8217;ve filed bug reports and if anyone has fixed this let me know.&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;See All Available Snippers&lt;/td&gt;
		&lt;td&gt; Use Menu &lt;/td&gt;
		&lt;td&gt;:Rabbrev&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Syntax Highlighting&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Set syntax highlighting to (e.g.) textile&lt;/td&gt;
		&lt;td&gt; Varies depending on highlighter. Select manually at the bottom of the screen. &lt;/td&gt;
		&lt;td&gt; :set syntax=textile &lt;br /&gt;
&lt;em&gt;You probably won&amp;#8217;t need this since &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; will automatically figure out the appropriate syntax highlighter.&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Turn on syntax highlighting&lt;/td&gt;
		&lt;td&gt; No option to enable/disable &lt;/td&gt;
		&lt;td&gt; :syntax on&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Turn off syntax highlighting&lt;/td&gt;
		&lt;td&gt; No option &lt;/td&gt;
		&lt;td&gt; :syntax off&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Formatting&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Reformat selection to according to wrap settings &lt;/td&gt;
		&lt;td&gt;⌃Q &lt;/td&gt;
		&lt;td&gt;gq &lt;em&gt;gqgq, i.e. the command twice, to reformat the current line&lt;/em&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Other&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Duplicate line/selection&lt;/td&gt;
		&lt;td&gt; ⌃ + ⇧ + D&lt;/td&gt;
		&lt;td&gt; yyp &lt;br /&gt;
&lt;em&gt;y copies line then p pastes in below.&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Add placeholder text&lt;/td&gt;
		&lt;td&gt;lorem + tab&lt;/td&gt;
		&lt;td&gt; lorem + enter&lt;br /&gt;
&lt;em&gt;Assumes you have add the following to your vimrc.local:&lt;br /&gt;
&amp;quot; anytime &amp;#8216;lorem&amp;#8217; is typed in, replace it with placeholder text&lt;br /&gt;
abbr lorem Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras a ornare metus. In justo metus, auctor nec semper in, laoreet porttitor augue. Maecenas tortor libero, dignissim vel placerat sit amet, malesuada ut quam. Curabitur vitae velit lacus, sed imperdiet sapien. Sed posuere, odio nec pharetra adipiscing&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Overwrite Mode&lt;/td&gt;
		&lt;td&gt; ⇧ + ⌥ + O &lt;br /&gt;
&lt;em&gt;Then start typing text&lt;/em&gt; &lt;/td&gt;
		&lt;td&gt; R &lt;br /&gt;
&lt;em&gt;Then start typing text&lt;/em&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Edit ends of selected lines&lt;/td&gt;
		&lt;td&gt;⌘ + ⌥ + a&lt;/td&gt;
		&lt;td&gt; &lt;br /&gt;
⌃ + V to enter &lt;span class=&quot;caps&quot;&gt;VISUAL&lt;/span&gt;-&lt;span class=&quot;caps&quot;&gt;BLOCK&lt;/span&gt; mode&lt;br /&gt;
select your lines&lt;br /&gt;
$ to go to the end of the selection&lt;br /&gt;
A to enter &lt;span class=&quot;caps&quot;&gt;EDIT&lt;/span&gt; mode at the end&lt;br /&gt;
⎋ when you are finished_ &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; Edit start of selected lines&lt;/td&gt;
		&lt;td&gt; No equivalent &lt;/td&gt;
		&lt;td&gt; Sane as above, except you press I instead of A&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;Wrap selected text in P tags&lt;/td&gt;
		&lt;td&gt; ⇧ + ⌃ + W &lt;/td&gt;
		&lt;td&gt; ystp &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Help&lt;/h2&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;td&gt;Search help for &amp;#8216;grep&amp;#8217;&lt;/td&gt;
		&lt;td&gt;Click help menu and search for help&lt;/td&gt;
		&lt;td&gt;:help grep&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h2&gt;Email Me If I Left Something Out&lt;/h2&gt;
&lt;p&gt;Or if you can find a more idiomatic way of doing any of the above commands.&lt;/p&gt;
&lt;h2 id=&quot;vim_training_resources&quot;&gt;Recommended Resources For Learning Basic &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Remember the key is to train your fingers. Don&amp;#8217;t just read the text; open up a blank file and try out different commands. If you want to get good at &lt;span class=&quot;caps&quot;&gt;VIM&lt;/span&gt; you need to have the confidence to tear a file to pieces your training sessions.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.derekwyatt.org/vim/vim-tutorial-videos/&quot; title=&quot;Highly recommended, if you can tolerate his excitement&quot;&gt;Derek Wyatt&amp;#8217;s Video Series&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://alfmikula.blogspot.com/2010/11/using-spaced-repetition-software-to.html&quot; title=&quot;My Personal Favourite&quot;&gt;Spaced Repetition Systems For Drilling&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;http://stevelosh.com/blog/2010/09/comi
