Table of Contents

1 Preface

1.1 About the Documentation

The intended purpose of the documentation is to give an understanding of the main features offered by TextMate and should provide you with those details which are not easily found alone by trial-and error. The documentation is not exhaustive.

You are supposed to already know what a text editor is, in particular have some experience with Cocoa’s text editor control (used e.g. in TextEdit, Mail, and Xcode). While TextMate does not use that control, it does for the most part mimic its behavior.

If you want to print this documentation then here is a printable version.

1.2 Philosophy of TextMate

From UNIX we get that Tasks and Trends Change. In concrete terms this means that instead of writing a command (in UNIX) to solve the problem at hand, we find the underlying pattern, write a command to solve types of that problem, and then use it in a script.

This gives us a command which we can re-use in the future for many problems of the same type, and since it‍ is generally much easier (and more flexible) to piece together a script of different commands, than it is to write a specific command for the task, this is a big gain in productivity. Especially since we actually do not write the command in the first place, we use an existing command that has already been written for this type of problem.

There are two ways in which TextMate leverages that philosophy. First it has good shell integration, so if you are skilled in using the UNIX shell, you should love TextMate for this integration.

But more ambitiously, TextMate tries to find the underlying patterns behind automating the tedious, being smart about what to do, and then provide you with the functionality so that you can combine it to settle your particular needs.

Granted, TextMate is not the first text editor which tries to be broad, but from Apple we get the venerable Keep It Simple. So even users with no or little experience with scripting and regular expressions are able to customize TextMate in ways that no other editor would have allowed them to.

That said, the philosophy of TextMate is also to Educate the User. So to fully capitalize on what TextMate gives you, you should learn a scripting language, regular expressions, and should understand TextMates scope and snippet system (to some degree also language grammars) and have an idea about the shell infrastructure provided (in particular environment variables, pipes, and stdin/stdout).

1.3 Terminology

For the most part TextMate and this documentation abides by Apples terminology. Below is a table of terms that might be a source of misunderstandings.

Term Explanation

Caret

The text insertion point.

Cursor

Mouse pointer.

Document

This refers to a file when it is loaded into TextMate (for the purpose of being edited). Old-timers often refer to this as the buffer.

Directory

This is sometimes used instead of folder. Mainly folder is used when talking about the GUI and directory is used when talking about shell related things.

Generally TextMate and this documentation use the glyph representation of a key. Below is a table with most glyphs, the name of the key (as used in this documentation) and a short explanation.

If you are unsure of the location of a key, you can bring up the Keyboard Viewer, which you can add to the Input menu in the International pane of System Preferences.

Glyph Key Name Explanation

Control

This key is generally in the lower left corner of the keyboard (and symmetrically placed in the right side). In addition to key equivalents, this key is also used with a mouse click to bring up context sensitive menus.

Option

This is next to the control key and often bears the label Alt. If you hold down the option key while selecting text with the mouse, the selection will be rectangular. It is also possible to single-click with the option modifier down to place the caret unrestrained of line-endings. Together with shift, it does a (rectangular) selection to where you click.

Command

The command key is also referred to as the Apple key since it has an apple symbol on it ().

Shift

The shift key should be well-known. When used together with a mouse click, it extends the selection.

Escape

The escape key is generally in the upper left corner of the keyboard. This key can be used to dismiss (cancel) panels, which means dialogs and some (but not all) windows. In TextMate it‍ is also used to cycle through completion candidates.

Enter

The enter key is on the numeric keypad (and is not the same as return). On laptops it‍ is fn-return.

Return

The return key should be well known.

Forward Delete

This is often just called delete and on the keyboard has a label of Del or Delete.

Backward Delete

Often called backspace. On my keyboard this just has a left pointing arrow on the key (←).

﹖⃝

Help

The Help key is located above forward delete, but not all keyboards have it. Generally it has the word Help on the key, but it has been known as the Ins key as well.

Home

The Home key scrolls to the beginning of the document, but does not move the caret.

End

The End key scrolls to the end of the document, but does not move the caret.

Page Up

Scrolls up a page, but does not move the caret. If used with the option modifier it will scroll the caret. Likewise will shift cause a selection.

Page Down

Scroll down a page without moving the caret. Using the option key will cause the caret to be moved.

Tab

The tab key is used to insert a tab character (or equivalent amount of spaces if soft tabs is enabled). In normal controls it advances the focus to the next control.

Back-tab

The back-tab key is achieved by holding down shift while using the normal tab key.

1.4 Limitations

TextMate is work-in-progress. One current key limitation (for non-Western users) is support for international input modes (e.g. CJK), proportional fonts, right-to-left text rendering and other (UniCode) features. As the author, I do understand the desire from users to have TextMate support these things, but currently proper support for this is a long-term to-do item.

And on the topic of limitations, I am also aware of the desire for (s)ftp integration, code hinting, split views, better printing, indented soft wrap, coffee making, and literally hundreds of other user requests. You will be able to find my comments on most feature requests by searching the mailing list archive, but I do not give estimates or timeframes, other than what version number I plan for something to appear in.

2 Working With Multiple Files

2.1 Creating Projects (With Tabs)

In the current version of TextMate (1.1) file tabs are only supported when a project is created. Fortunately it is easy to create a project, namely by selecting File → New Project (⌃⌘N).

This opens a window which looks like the one below.

It is possible to add files either by dragging them to the (project) drawer, or use the “Add Existing Files…” action in the project drawers action menu (the one with the gear icon).

Another way to create a project is by dragging files directly onto the TextMate application icon (shown e.g. in the dock). This is a shortcut for creating a new project consisting of these files.

One minor detail is that when creating a project this way, you will not be asked if you want to save the project, when it is closed.

The advantage of saving a project is to keep state (like which files were open) and to be able to quickly re-open a particular set of files. If you leave a (saved) project open when you quit TextMate, it will automatically re-open that project the next time you launch TextMate.

It is also possible to create projects from the terminal e.g. using the mate shell command.

2.1.1 Auto-Updating Projects

When you want to have your project mimic the files and folders on disk, you can drag a folder either onto the TextMate application icon, or into the project drawer.

TextMate will then create a folder reference where it automatically updates the contents of the folder when it changes on disk.

Currently (updating) is done when TextMate regains focus and can be slow for some network mounted disks, in which case you may want to settle for only adding individual files to the project (which can be grouped and re-ordered manually to mimic the structure on disk).

The refresh delay for network mounted disks will be addressed in a future release.

2.1.2 Filtering Unwanted Files

When using folder references, you may want to have certain files or folders excluded from the project. This can be done by changing the file and folder patterns found in Preferences → Advanced → Folder References.

These are regular expressions which the full path of each file and folder is matched against. If the pattern does match the item, it is included, otherwise it gets excluded. To reverse that, so that items which match are instead excluded from the project, prefix the pattern with an exclamation point (!).

The patterns are only used when creating new folder references. For existing folder references one can select the folder reference in the project drawer and use the circled I button in the project drawer to edit the patterns.

The complexity of this system will be addressed in the future.

2.1.3 Text and Binary Files

You can either single or double click files in the project drawer. If you single click them, and the file type is text, they open as a file tab in the main window.

If you double click a file, it will open using the default application. Note that folders can also be double clicked, for example Interface Builders nib files will appear as folders, but can still be double clicked (and will then open in Interface Builder).

As mentioned, only text files will open in the main window, when single clicked. The way TextMate determines if a file is text is by extension, and if the extension is unknown, it scans the first 8 KB of the file, to see if it is valid UTF-8 (which is a superset of ASCII).

If TextMate does not open your file, and it does have an extension, you can bring up the action menu for that file and pick the last item, which should read: Treat Files With “.«ext»” Extension as Text.

2.1.4 Positioning the Project Drawer

The project drawer will by default open on the left side of the project window. If there is no room for it to open there, it will instead use the right side. This setting is sticky, so in the future it will use the right side as default, if it has once been opened on that side.

To move it back to the left side you need to close the drawer (View → Hide Project Drawer) and then move the project window so that there is no longer room for the drawer on its right. When you then re-open the drawer, it will again appear on the left side, and use that as the new default.

The opposite can be done to force it to open on the right side.

2.2 Find and Replace in Projects

Using Edit → Find → Find in Project… (⇧⌘F) will bring up the window shown below.

From here it is possible to search all (text) files in the current project and do replacements. After pressing Find it is possible to either press Replace All, or select which matches should be replaced, which change the Replace All button title to Replace Selected.

Currently it is not possible to limit the source to other than the full project (with all text files), but as a workaround, for when you want to search only a subset of your project, it is possible to select what you want to search in the project drawer, and drag the selection to the TextMate application icon to create a new scratch project, then perform the find in that project, and close it when done.

2.3 Moving Between Files (With Grace)

When working with projects there are a few ways to move between the open files.

The most straightforward way is by clicking on the file tab you need. Doing this from the keyboard can be done by pressing ⌘1-9, which will switch to file tab 1-9.

You can also use ⌥⌘← and ⌥⌘→ to move to the file tab to the left or right of the current.

It is possible to re-arrange the file tabs by using the mouse to drag-sort them (click and hold the mouse button on a tab and then drag it to the new location). This should make it possible to arrange them so that keyboard switching is more natural.

One more key is ⌥⌘↑ which cycles through text files with the same base name as the current file. This is mostly useful when working with languages which have an interface file (header) and implementation file (source).

When you want to move to a file which is not open you can use the Go to File… action in the Navigation menu (bound to ⌘T). This opens a window like the one shown below.

This window list all text files in the project sorted after last use, which means pressing return will open (or go to) the last file you worked on. So using it this way makes for easy last-recently-used switching.

You can enter a filter string to narrow down the number of files shown. This filter string is matched against the filenames as an abbreviation, and the files are sorted according to how well they fit the given abbreviation. For example on the picture the filter string is otv and TextMate determines that OakTextView.h is the best match for that (by placing it at the top).

The file I want is OakTextView.mm which rank as #2. But since I have once corrected it in the past, TextMate has learned that this is the match that should go together with the otv filter string, i.e. it is adaptive and learns from your usage patterns.

3 Navigation / Overview

3.1 Bookmarks

If you need to move the caret to somewhere else in your document, and want a quick way to return, you can place a bookmark at the current line.

This is done either by clicking in the gutter (in the column dedicated to bookmarks) or pressing ⌘F2. The bookmark will be indicated with a star as shown below.

When you want to return you can press F2, which moves you to the next bookmark in the document. If there are more than one bookmark, you can press F2 repeatedly. ⇧F2 will move to previous bookmark.

3.2 Collapsing Text Blocks (Foldings)

When working in a language which has start/end markers for blocks, like {}, doend, <tag></tag>, and similar, TextMate can spot these blocks and will show up/down arrows in the gutter for the start/end marker.

When these arrows are present, it is possible to fold the block into a single line either by using the mouse and clicking on the up/down arrow, or pressing the F1 key. This will make the arrow in the gutter point to the right, and indicate that the entire block got folded by placing an ellipsis marker at the end of the line. An example where the two sub-blocks of the constructor has been folded can be seen below.

With text folded, it is possible to unfold it with F1 or clicking either the arrow in the gutter or the ellipsis image. It is also possible to hover the mouse pointer on the ellipsis image to get a tool tip which show the contents of the folded block. The latter is shown on the following picture.

A word of caution: the folding system is based on both having clear indent markers and having the fold start/stop markers use the same indent level. This means that folding purely based on indent or where the start/stop markers do not align, is currently not supported.

3.2.1 Customizing Foldings

As mentioned the folding system uses explicitly defined start and stop markers. TextMate knows about these from the language grammar where you can setup a foldingStartMarker and foldingStopMarker regular expression.

Shown above are the HTML folding patterns, which are all but simple because they fold on a selected set of tag pairs, HTML comments, some Smarty tags, and start/stop braces when either last on the line or used in embedded code tags like this:

<?php if(something) { // user is authenticated ?>

   ...

<?php } // user is authenticated ?>

To define that a block starts when { is the last non-space character on the line, and stops when } is the first non-space character on the line, we can use the following patterns:

foldingStartMarker = '\{\s*$';
foldingStopMarker = '^\s*\}';

3.3 Function Pop-up

For languages where it is supported, the rightmost pop-up in the status bar show the current “symbol” (often the function prototype or heading above the caret).

It is possible to click on the pop-up to get a list of all the symbols in the current document, and move the caret to one of these. This looks like shown below.

For keyboard navigation there is also Navigation → Go to Symbol… (⇧⌘T) which opens a panel like the one shown below. The contents of this is the same as the pop-up from the status bar, but this panel support filtering similar to the Go to File… panel (i.e. where the filter string is treated as an abbreviation, and matches are ranked according to how good a fit the abbreviation seems to be).

The panel can be left open, and will automatically update when the document is edited. If you single-click an item in the list, the caret will move to the symbol clicked. Double-click will do the same, but also close the panel.

3.3.1 Customizing the List

The symbol list works using language grammars and scope selectors. A language grammar assign names to each element in the document, and a scope selector is capable of targeting a subset of the document based on these names. Normally the parallel is HTML and CSS, e.g. we can make a theme item which sets the background to blue, and then use a scope selector to pick which elements in our document we want this blue background applied to.

Bundle preferences work like theme items, except that instead of changing visual settings they (generally) change non-visual settings. One setting is the showInSymbolList. By setting this to 1 and using a scope selector which e.g. target all function names, we are in practice using that scope selector as a query to extract all function names from the document, for use in the symbol list.

So to populate the symbol list we need to:

  1. Make sure the language grammar assigns a name to what we want to show.

  2. Create a bundle preferences item that sets showInSymbolList to 1 and use a scope selector that match the symbols we want to have in the symbol list.

In addition to the showInSymbolList setting there is a symbolTransformation setting which is one or more regular expression substitutions which are performed on the text extracted. The value of this setting should be: s/«regexp»/«format»/«options» optionally followed by ; and more substitutions. It is also possible to put comments in the value, these start with # and end at the next newline.

So if we want to show Markdown headings in the list, which are lines that start with one or more # marks, then we first make sure our language grammar assigns a name to these, for Markdown that can be done with this rule (in the language grammar):

{  name = 'markup.heading.markdown';
   match = '^#{1,9}\s*(.*)$';
},

Now we can target all headings using a scope selector of markup.heading.markdown. So we create a bundle preferences item that simply is:

{  showInSymbolList = 1;   }

This will include the leading # marks in the list, which is undesired. We can either assign a name (via the language grammar) to the actual title, or we can perform a regular expression substitution to get rid of the leading # marks. The latter has the advantage that we can change these to indent, so that is what we do, by changing the preferences item to:

{  showInSymbolList = 1;
   symbolTransformation = '
      s/(?<=#)#/ /g;          # change all but first # to m-space
      s/^#( *)\s+(.*)/$1$2/;  # strip first # and space before title
   ';
}