Learn How to be a TextMate Champion


TextMate is, by far, the preferred text-editor for most web developers on the Mac. In today's screencast we'll be taking a look at some of the features most developers simply don't use which can massively increase your productivity by allowing you to type less!

Not a Mac person? Jeffrey has a screencast titled "How I Can Code Twice As Fast As You" showing how to perform similar actions using a "text expander" application in Windows.

Full Screencast

Shortcuts Used

You can view all of TextMate's shortcuts and functions under the 'Bundles' menu. Here are some of the ones I use regularly:


Option (Alt)
Escape (esc)
↓ ← ↑ → Keyboard arrow keys


Shortcut Action
⌃ ⇧ , New HTML tag pair
⌥ ⎋ Tag/attribute auto-completion
⌘ ⇧ 7 Convert selection to HTML entities
! ⇥ Internet Explorer Conditionals
⇧ ↩ Line Break
⌃ ⇧ V Validate HTML / CSS
link ⇥ Stylesheet Link Tag
style ⇥ In-line style block
scriptsrc ⇥ External JavaScript tag
script ⇥ In-line JavaScript block


Shortcut Action
php ⇥ <?php ?>
echo ⇥ <?php echo ?>
if ⇥ <?php if (...): ?>

<?php endif ?>

ifelse ⇥ <?php if (...): ?>

<?php else: ?>

<?php endif ?>

for ⇥

foreach ⇥

while ⇥

array ⇥

switch ⇥

case ⇥
As you'd expect.
req ⇥

req1 ⇥

incl ⇥

incl1 ⇥
require 'file';

require_once 'file';

include 'file';

include_once 'file';
$_ ⇥ Select $_['POST'], $_['GET'] etc. (Global Arrays)
⌃ ⇧ V Validate syntax
⌘ ⇧ R Run PHP file


Shortcut Action
if ⇥

ife ⇥ (if, elsif)

unless ⇥

while ⇥
As you'd expect.
req ⇥ require ""
reqg ⇥ require "rubygems"

require ""
Hash ⇥ { |hash, key| hash[key] = }
: ⇥ :key => "value",
File ⇥ Select for different 'File' object methods (read, write etc.)
⌘ R Run Ruby file


Shortcut Action
cla ⇥ Create Rails Controller
flash ⇥ flash[:notice] = ''
ra ⇥ render :action => ''
vp ⇥ validates_presence_of :input
vl ⇥ validates_length_of :input, :within => 1..12
⌃ P params[:object]
⌃ J session[:object]
⌃ ⇧ . <%= %>
ff ⇥ <% form_for @model do |f| -%>

<% end -%>

f. ⇥ Select for Rails' form helper - label, field, password, textarea, checkbox etc.
slt ⇥ <%= stylesheet_link_tag '' %>
jit <%= javascript_include_tag '' %>
⇧ ⌥ ⌘ ↓ Go to appropriate controller, model, view etc. for current file
mcol ⇥ Use in migrations. Select to add, edit, rename, remove columns etc.

Create Your Own Shortcut/Hotkey

We're going to create a shortcut (accessed with ⌘⇧A) to wrap the currently selected text in a link, and jump you straight to the href="" attribute to enter the URL.

In TextMate, go to "Bundles > Bundle Editor > Show Bundle Editor" (or press ⌃⌥⌘B). This is what my editor looks like. Yours may look different as I have added some custom Bundles and removed some for languages I don't use:

Click on the HTML drop-down (bundle), click the + at the bottom-left of the window and select 'New Snippet'. Name this snippet 'Wrap Link' then for the 'Activation', select 'Key Equivalent' and in the box enter the key combination you wish to use (eg. ⌘⇧A).

Inside the text-area enter:

&lt;a href=&quot;&quot;&gt;$TM_SELECTED_TEXT&lt;/a&gt;

$TM_SELECTED_TEXT is a variable containing the selected text. Close the window and try it out. Open a document in TextMate, highlight some text and press your key combination. The selection will be wrapped in anchor tags.

However, as it is now, you still have to move your cursor into the href="" attribute to enter the actual link. Wouldn't it be easier if our cursor moved itself there automatically?

Change the 'Wrap Link' command to the following:

&lt;a href=&quot;${1}&quot;&gt;$TM_SELECTED_TEXT&lt;/a&gt;

The ${1} tells TextMate where to place the cursor after performing the task. You can place ${2}, ${3} etc. and then move throughout them using the tab key.

Finally, change the command to:

&lt;a href=&quot;${1}&quot;&gt;${2:$TM_SELECTED_TEXT}&lt;/a&gt;

You can add default text at a location using ${2:Default text} . 'Default text' will display, and automatically highlighted when you tab into it.

In our case, we have set the selected text as a tab location for circumstances when you may want to change the original text.

You could also 'mirror' text entered at tab points, like so:

&lt;p&gt;Text: ${1}&lt;/p&gt; 
&lt;p&gt;Some other text: ${2:blah de blah de blah}&lt;/p&gt; 
&lt;p&gt;Mirror of 1: ${1}&lt;/p&gt;

Whatever you then enter on the first tab, will automatically be entered in other positions which hold the same value.

Further Examples:

Personally I've created my own bundles for including the jQuery libraries, entering 'Lorem Ipsum' text, and also for writing Nettuts articles. For example:

jQuery Snippets

Find yourself using mindlessly entering jQuery tags? Try these:

'jQuery CDN' accessed with inc-jquery tab-trigger:

&lt;script src=&quot;; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

'jQuery UI CDN' accessed with inc-ui tab-trigger:

&lt;script src=&quot;; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

'jQuery Inline Script' accessed with inline-jquery tab-trigger:

&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt; 
  \$(function() { 

'jQuery Document Ready' accessed with jquery tab-trigger:

\$(function() { 

Note: The back-slashes at the start of $(function() { is to escape the $ character – otherwise TextMate will think it's a variable for it to try and render!

You could also simply assign all these to a jquery tab-trigger, then when you execute it, you will get a drop-down menu to choose from. This is useful if you prefer not to memorise huge groups of snippet names!

Nettuts Snippets

I also have a bundle for the various tags Nettuts articles depend upon, such as:

'Pre Code Block' accessed using nt-pre tab-trigger:

&lt;pre name=&quot;code&quot; class=&quot;${1:php}&quot;&gt; 

'Tuts Image' access using nt-img tab-trigger:

&lt;div class=&quot;tutorial_image&quot;&gt;&lt;img src=&quot;images/${1}&quot; border=&quot;0&quot; /&gt;&lt;/div&gt;

When writing articles I use a small template to make it easier to read when proof-reading. This snippet has an example of 'mirroring' on the Title and H1 tags. I access this using the nt-template tab-trigger:

&lt;style type=&quot;text/css&quot; media=&quot;all&quot;&gt; 
body{color:#42423D;font-family:Arial,Helvetica,sans-serif}p,li,pre,blockquote{line-height:1.5em;font-size:0.9em}code{background-color:#efefef;color:#000;font-family:'Courier New',Courier,monospace;font-size:1.1em;margin:0 3px;padding:0 3px}code.filename{background-color:#f9f9f9;color:#42423D;font-family:'Courier New',Courier,monospace;font-size:1.1em;margin:0}#wrap{margin:15px auto;width:640px}code{font-size:1em !important}#meta{border-bottom:1px solid #f0f0f0;margin:40px 0 20px 0;overflow:hidden;padding-bottom:20px}#meta h1{margin-top:0}#meta img{border:5px solid #f0f0f0;float:left;margin:0 10px 10px 0}#meta p{font-size:0.9em;font-style:italic}.tutorial_image{background-color:#f0f0f0;border:1px solid #CECFD0;margin-bottom:10px;padding:10px 0;text-align:center}.tutorial_image img{border:1px solid #CBCBCB}.webroundup{padding:0px;margin:0px}.webroundup li{padding:0px;margin:0px;list-style:none;margin-bottom:20px;clear:both;margin-left:0px;padding-left:0px;background:none}.webroundup a{background-color:#468175;color:#fffffe;padding:3px 6px 3px;text-decoration:none;font-size:11px}.webroundup a:hover{background-color:#222323}.webroundup div{padding:10px;background-color:#f9f9f9;border:1px solid #cbcbcb;float:left;margin-right:15px;margin-bottom:20px}.webroundup img{border:1px solid #cbcbcb}.webroundup h4{display:block;margin-bottom:10px}.clear{clear:both;} 
&lt;div id=&quot;wrap&quot;&gt; 
&lt;div id=&quot;meta&quot;&gt; 
  &lt;img src=&quot;images/${3:postimg.jpg}&quot; /&gt; 
  &lt;p&gt;${2:Summary text}&lt;/p&gt; 
&lt;p&gt;${5:Start typing! Use H3 for headings and H4 for sub-headings}&lt;/p&gt; 
&lt;/div&gt;&lt;!-- #wrap --&gt;
Related Posts
  • Web Design
    HTML & CSS
    Build a Dribbble Portfolio Grid With Flexboxgrid and JribbbleFlexboxgrid dribbble
    Flexboxgrid is a new framework which allows you to combine the predictability and common language structure of a grid system with the flexibility and simplicity of flexbox. Today, we will walk through the basics of using Flexboxgrid, and use it to build a simple Dribbble feed. Let's get started!Read More…
  • Web Design
    Complete Websites
    Building the Responsive Timeline Portfolio PagePortfolio thumb
    During this tutorial we will be building the fantastic Timeline Portfolio as seen in an earlier tutorial by Tomas Laurinavicius. We will be using some responsive techniques as well as CSS3 animations, Sass and a little bit of jQuery.Read More…
  • Web Design
    Build a Top Bar Off-Canvas Navigation With Foundation 5Foundation menu
    Today, we are going to combine ZURB's Foundation 5 Off-Canvas feature with our top bar navigation. The result will be a nice custom navigation for desktop users and a sleek off -canvas menu for tablet and mobile users. Read More…
  • Code
    HTML5: Battery Status APIPdl54 preview image@2x
    The number of people browsing the web using mobile devices grows every day. It's therefore important to optimize websites and web applications to accommodate mobile visitors. The W3C (World Wide Web Consortium) is well aware of this trend and has introduced a number of APIs that help with this challenge. In this article, I will introduce you to one of these APIs, the Battery Status API.Read More…
  • Web Design
    Case Studies
    How They Did It: Typekit's New HomepageTypekit retina
    Typekit recently redesigned their homepage with some new services in mind. When Typekit joined Adobe, they set out to bring us a new way to handle fonts on the web. Not only did they create a fairly simple way to embed fonts on the web, but they have now officially launched a desktop sync option, which allows Creative Cloud subscribers to sync fonts to their computer directly from Typekit. This has been in a beta form for a while now, and provides a much easier route to local fonts than finding them elsewhere!Read More…
  • Web Design
    Finishing Off the Merry Christmas Web App InterfaceXmas build 1 retina
    In this tutorial we will finish off our web app front-end so it all looks perfect and functions nicely on all screen sizes. Last time, we rounded off by styling the message boxes, leaving just the content left to do. Shall we dive right in? Ok!Read More…