TextMate Wiki

Updated 10122022-013451


The TextMate Wiki (at GitHub) is meant as a knowledge base for users of and contributors to TextMate.

While TextMate is under development, things will generally be documented first in the change log, then this wiki, and finally the manual. (Presently, the manual hasn’t been updated for 2.0.)

Issue Tracker

Documentation

Contributing

Issue Tracker


As of this writing, the Issue Tracker is not public.
See http://macromates.com/support to contact support or report an issue.


Bug Reports

The issue tracker at GitHub is for tracking bugs. If you wish to report a bug, please first read how we want bug reports written.

Questions, Comments, and Troubleshooting

Use one of the following:

You can also use any of these for bug reports.

If you’re not sure if something is really a bug, or how to reproduce it, or if it’s already known, etc., please use one of the above channels (instead of the issue tracker).

The Issue Tracker

The Issue Tracker has some overhead (for the development team, presently just one person) that the above channels do not.

With the issue tracker, something as simple as replying to a known issue with “yeah, we know about that, thanks!” becomes surprisingly complex. It requires into visiting the issue in a web browser, assigning it a label, doing a search on GitHub Issues (which is nothing like Google’s) to mark references to the old issue(s), and finally closing the new one.

Perhaps it doesn’t sound like much, but after about a thousand issues in half a year, it does feel like an unnecessary distraction. It’s also something that is difficult to outsource, as Pull Requests also come in via the Issue Tracker. Further complicating the matter is that we reference Issue numbers for bugfix commits.

Other Issues

To keep the Issue Tracker useful, we generally close issues which are not bug reports. We may not always comment, but generally a label should be assigned.

Here’s an explanation of some of the typical labels used to close issues:

Also, please remember that while TextMate is developed in a fairly open way, the program’s evolution is **not*- dictated by users (via the issues they open).


Before reporting a bug try first [[reverting to defaults]]

A bug report should contain these 4 things:

  1. Steps to reproduce: Give **detailed*- steps on how to reproduce the problem.

  2. Expected result: It’s important to include the result you’re expecting, as it might differ from how the program was designed to work.

  3. Actual result: This is also important, since it’s possible that following your steps on a different system doesn’t reproduce the issue.

  4. Environment: This includes:

Your Bug Report’s Title

See this great article (by Jakob Nielsen) on writing headlines, page titles, and subject lines.

Adding Pictures

As they say, “a picture is worth a thousand words”…but that is **not*- what we want in a succinct bug report! (Not to mention the plethora of other issues related to submitting bug reports as images.)

Only include pictures or movies as extra material, when it clarifies your bug report in ways that cannot be expressed in text. (For example, if text is garbled, it’s useful to include an image of *how- exactly it gets garbled.)

Opening an issue saying “syntax highlight is incorrect” with nothing besides a screenshot is not acceptable.

Crashes or Hangs

Unless you have steps to reproduce, there’s generally no need to report a crash. We already get crash reports from users who haven’t opted out. (You can change this in Preferences → Software Update.)

Reporting Crashes

If you’re opening an issue about TextMate crashes, please include the corresponding crash report.

You can find a list of submitted reports in Notification Center. Just click the entry to open an online version. This also provides you with a URL to include in the issue (please do!).

You can also find crash reports for your system online under my crashes.

Reporting Hangs

Hangs are different than crashes. If the program locks up, you should find (or create) a “spin report”. Normally, you can find these here:

/Library/Logs/DiagnosticReports/TextMate*«time»*«host».hang

If you need to *generate- a spin report while TextMate is locked up, here’s how:

  1. launch Activity Monitor
  2. select TextMate
  3. select then Sample Process (⌥⌘S).
  4. paste the spin report online via [https://gist.github.com] GitHub’s issues don’t allow file attachments

TextMate has a few settings which are not exposed in the GUI.

You can change these with the defaults shell command. (Make sure you do this while TextMate is **not*- running!)

Settings

Key Description Type
disableTypingPairs When you type an opening brace, parenthesis, quote character, or similar, TextMate will insert the closing character. boolean
disableFolderStateRestore When opening a folder TextMate will restore open tabs and file browser state from the last time you had this folder open. boolean
disableAntiAlias Disable font anti-alias. boolean
disablePersistentClipboardHistory Don’t store clipboard history in ~/Library/Application Support/TextMate/ClipboardHistory.db. boolean
disableTabAutoClose Don’t close excess tabs when the tab bar overflows. boolean
fileBrowserOpenAnimationDisabled This is for the zoom animation shown when opening items via TextMate’s file browser. boolean
alwaysFindInDocument Set this if you want ⌘F to always set the “in” pop-up to “document” (by default it searches “selection” when there is a multi-line selection. boolean
fileBrowserStyle Set this key to SourceList if you want TextMate’s file browser to use the “source list” style as seen in Finder’s sidebar. string
hideStatusBar Disable the status bar shown below the text area. boolean
fontAscentDelta Increase/decrease TextMate’s default line ascend float or integer
fontLeadingDelta Increase/decrease TextMate’s default line lead float or integer
environmentWhitelist Colon-separated list of environment variables that TextMate should pass to a child process. Items with an asterisk are treated as a glob. You can use $default for the default whitelist. Example: $default:MANPATH:*EDITOR. TextMate sets up HOME, PATH, TMPDIR, LOGNAME, and USER. If you whitelist any of these, then the variable (if set) will inherit from the parent process instead. string
lineNumberFontName Allows the use of a different font for the line number display. string
lineNumberScaleFactor Allows shrinking of the line number display, defaults to 0.8 float or integer
showFavoritesInsteadOfUntitled Show Recent Projects/Favorites window on startup and re-activation (instead of having an untitled window created), defaults to false. boolean
enableLoopFilterList In the chooser lists (fuzzy file finder, bundle item chooser, and symbol list) it is now possible to make the selection loop around, that is, move from first to last item with arrow up, etc. Defaults to false. boolean
tabItemMinWidth Minimum tab width, defaults to 120. integer
tabItemMaxWidth Maximum tab width, defaults to 250. integer
tabItemLineBreakStyle Tab truncation style, defaults to 5. Possible values:

2 = Simply clip
3 = Truncate at head of line: "...wxyz"
4 = Truncate at tail of line: "abcd..."
5 = Truncate middle of line: "ab...yz"
integer

For the integer and float keys, you **must*- use -float or -integer when setting the value.

macOS Settings

These are settings that macOS uses to trigger some features on a per-app basis and can be used to enable or disable the feature in TextMate.

Key Description Type
NSAutomaticPeriodSubstitutionEnabled Allows using double-space to end a sentence and add a period, disabled by default. boolean

Disabling Extended Attributes

TextMate use extended attributes to store caret position, etc.

On file systems which don’t support extended attributes (most network file systems), OS X will create an auxiliary file with a dot-underscore prefix (e.g., .«*filename»).

If you don’t want these files, you can disable the use of extended attributes. This is presently controlled with the volumeSettings key. Its values are:

  1. an associative array with path prefix, and
  2. another associative array with settings for that path. (Presently, only extendedAttributes is supported.)

*Example:- If we wanted to disable extended attributes for files under /net/:

defaults write com.macromates.TextMate volumeSettings '{ "/net/" = { extendedAttributes = 0; }; }'

Controlling Font Smoothing

Font smoothing refers to sub-pixel anti-alias on LCD screens. Apple’s font smoothing algorithm will often make light text on dark backgrounds appear bolder than the same text on a bright background.

For this reason, TextMate disables font smoothing for dark themes on high-DPI displays (retina Mac).

You can control the behavior with:

defaults write com.macromates.TextMate fontSmoothing «value»

Here «value» can be:

If you wish to restore the default value (3) it’s better to run the following, rather than explicitly setting the value to 3:

defaults delete com.macromates.TextMate fontSmoothing

Keybindings

Key bindings are consulted in the following order (first file with a binding wins):

~/Library/Application Support/TextMate/KeyBindings.dict
/path/to/TextMate.app/Contents/Resources/KeyBindings.dict
~/Library/KeyBindings/DefaultKeyBinding.dict
/Library/KeyBindings/DefaultKeyBinding.dict
/System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict

If you edit any these files, you’ll need to relaunch TextMate (⌃⌘Q) for changes to take effect.

Find and extend selection

These two action methods find the next/previous occurrence of the Find clipboard’s contents and selects it, while preserving the existing selection:

findNextAndModifySelection:
findPreviousAndModifySelection:

One could, for example, add this to the key bindings:

"@d" = ( "copySelectionToFindPboard:", "findNextAndModifySelection:" );

Indent-aware movement

If you want ⌘⇠, ⇧⌘⇠, ⌘⇢, ⇧⌘⇢, ⌘⌫, and ⌘⌦ to ignore leading indentation, add the following to your key bindings file:

"@\UF702"  = "moveToBeginningOfIndentedLine:";
"$@\UF702" = "moveToBeginningOfIndentedLineAndModifySelection:";
"@\UF703"  = "moveToEndOfIndentedLine:";
"$@\UF703" = "moveToEndOfIndentedLineAndModifySelection:";
"@\U007F"  = "deleteToBeginningOfIndentedLine:";
"@\UF728"  = "deleteToEndOfIndentedLine:";

Editing

Completion considers $var, @var, and var as different

This article explains how (word) “units” are setup in 2.0. This is what completion uses. For example :symbol is different than symbol, so one isn’t suggested when completing the other.

If you do not wish for punctuation to be considered part of (completion) units, then:

  1. Select the menu item: Bundles → Edit Bundles…
  2. In the column browser select: Source → Settings → Character Class: Punctuation
  3. In the drawer, change scope selector from punctuation.separator to punctuation
  4. Press ⌘S (Save), and close bundle editor

Be aware that definition of units are also used for word movement (⌥←/⌥→) and word selection (⌃W).

How do I set which characters are considered to be part of a word?

When determining what constitutes a word, the characterClass setting is first consulted (see the previous FAQ item). If this doesn't apply, then the wordCharacters setting is consulted.

You can set wordCharacters by creating a new settings item in the bundle editor with the value:

{ wordCharacters = `«value»`; }

The «value» is a string of which characters should be considered word characters; these are *in addition to- those already defined as word characters. If you wish, you can set the scope selector to limit the scope in which the characters should be considered a word character.

This is used for completion, word movement (⌥←/⌥→) and word selection (⌃W).

How to strip trailing whitespace on save?

There are currently two possible ways to do this (both of which use the semantic class system):

  1. You can use callback.document.export, which will filter the document that’s saved to disk (but *won’t- update the copy inside TextMate)
  2. The inverse is also possible: callback.document.will-save (which will update the copy in TextMate *before- saving)

Here is a bundle to strip whitespace that makes use of the callback.document.will-save class.

How to disable soft wrap?

The **View*- menu has a setting to toggle soft wrap. (It stores the setting for the “current file type”.)

*Even with soft wrap disabled,- there are settings in the Source bundle to enable indented soft wrap for comments in source files. These can be disabled by unchecking the “Enable this item” checkbox in the bundle editor.

For more info see this mailing list post about indented soft wrap.

How to disable auto-paired characters?

See hidden settings.

In TextMate 1.x, a return between {} was treated specially, giving you an indented caret on a blank line. This no longer works in the alpha.

This is a complicated issue, explained best in this mailing list post.

Indentation isn’t behaving correctly in some languages. How can I correct this?

The indentation rules have been given a higher importance in TextMate 2. As a result, some language rules aren’t up-to-date with the new precedence.

For bundle authors (or anyone who wants to get their hands dirty), the guide to indentation rules is in the 1.x manual.

Of course, indentation rules make no sense in certain languages; Python’s indentation, for example, is what determines scope, rather than delimiters. For these languages, you can disable the auto correction of indentation by adding a new settings item (scoped to the language) as follows:

{ disableIndentCorrections = :true; }

If you’d rather disable it for all languages, do the same thing without giving it a scope.

Projects

Where have the project files from 1.x gone?

Explicit project files aren’t currently supported.

When you open a folder, the folder is treated as a project. Thus, the file chooser (⌘T) and folder search (⇧⌘F) default to the folder. (See the manual for more details.)

You can customize folder settings with a .tm*properties file.

Allan’s written a couple posts in a longer thread about this:

How do I create a project with files/folders from different locations in the file system?

With the directory-centered focus, this is no longer directly possible. A simple workaround, however, is simply to add symlinks to the various other directories and files.

(*Note:- By default, *Find in Folder- does not follow symlinks. See other FAQs on how to make it follow symlinks.)

Interface

How can I open files with a single click?

In the file browser, single-clicking the icon will open the file.

If you think the click-target is too small, you can enable the single-click behavior for the text instead. Simply run the following in a terminal:

defaults write com.macromates.TextMate fileBrowserSingleClickToOpen -bool true

If you wish to select items, you must either click to the left of the text, or hold down command () when clicking the item’s text.

Aliased/linked folders in the file browser aren’t expandable.

This is similar to how Finder treats links. There’s currently no way to have them expand inline.

Known Limitations

I cannot get my bundles to appear inside TextMate.

For standard bundles you should install via Preferences → Bundles.

Third party bundles can be double-clicked which installs them in:

~/Library/Application Support/TextMate/Pristine Copy/Bundles

If you wish to edit the bundles and share your changes you should install (git clone) them to:

~/Library/Application Support/TextMate/Bundles

This way, TextMate won’t create delta files (which aren’t useful for sharing).

If you manually install bundles and they do not show up, your file system may lack support for fs-events. If this is the case, you will need to delete the cache and relaunch TextMate:

rm ~/Library/Caches/com.macromates.TextMate/BundlesIndex.plist

How do I get a web preview window that updates as I edit an HTML document?

The current plan is to generalize the update mechanism through the semantic class system, so it can be used in more cases.

However, this isn’t yet implemented, and subject to change.

Can rmate be used to open directories?

No—rmate simply sends a file back and forth. Opening a folder is way more complex.

Search

Is it possible to have Find in Folder follow symlinks?

Within the *Find in Folder- window, there’s a drop-down menu above the results. Enable “Follow Symbolic Links” in this menu.

*Note:- This *will not- resolve aliases created with Finder.

Bundle Items

Using Duplicate Line with multiple carets produces an error.

Duplicate Line is implemented as a command. Currently, commands aren’t supported (per sé) for multiple carets.

Migrating from 1.x

Migrating Personal Bundles

*Use this method to migrate your personally created bundles. To install *other*- bundles, check Preferences → Bundles.

Beta versions of TextMate required you to move your personal bundles into an Avian-bundle directory. This is no longer deemed necessary, since there is no longer a reason to open TextMate 1.x.

Note:


Many problems can be solved by reverting to default settings. To do so, quit TextMate, then remove the following files and folders:

  1. ~/Library/Application Support/TextMate
  2. ~/Library/Caches/com.macromates.TextMate/BundlesIndex.binary
  3. ~/Library/Preferences/com.macromates.TextMate.plist
  4. ~/.tm*properties

*Note:- Not all of these files/folders may exist, and any potential customizations will be lost.

*Note:- As .tm*properties files can be in arbitrary folders, you may have more than the one in your home folder. But if you never created any, there is no reason to go hunting for them; TextMate doesn’t create these by itself.

*See also:- Troubleshooting for TextMate 1.x.


By default, TextMate writes errors to the standard error (STDERR) file descriptor.

Unfortunately, this means that it is not visible anywhere, unless you are running TextMate from a terminal (i.e., /path/to/TextMate.app/Contents/MacOS/TextMate, NOT just mate).

How To Redirect Logging to a File

To redirect logging, set the LOG*PATH environment variable before launching TextMate. TextMate will then create TextMate.log in the LOG*PATH location.

It’s easy:

  1. In a terminal, run:
   launchctl setenv LOG*PATH "$HOME/Library/Logs"

  1. Launch TextMate.

That’s it!


Verification

If you want to verify, run this in your terminal:

tail -f ~/Library/Logs/TextMate.log

*NOTE:- Each time you launch TextMate, the log file is recreated. Thus, output from previous sessions is lost.



I/O

Display

Projects

Other

File Filtering Keys

These are all globs and perhaps a bit arcane.

The file browser, if it has a file, checks that file against the first key with a value in this order: excludeFilesInBrowser, excludeInBrowser, excludeFiles, exclude. If neither match, it then does the same with include keys, and if one match, it is included. Directories work the same, except using the Directories

The default include key is - (so no hidden files, although see the default .tm*properties which include .htaccess and .tm*properties). The default exclude key is the empty string (nothing matches).

Exclude Keys
Include Keys

spellingLanguage Values

These values depend on which dictionaries you have installed so not all may be available. (You can see a list of what is available from the Edit → Spelling menu.)

en → English
enAU → English (Australia)
en
GB → English (United Kingdom)
enCA → English (Canada)
da → Danish
fr → French
de → German
es → Spanish
it → Italian
pt → Portuguese
pt
BR → Portuguese (Brazil)
nl → Dutch
sv → Swedish
ru → Russian
pl*PL → Polish (Poland)


Atomic Saving - atomicSave Values

TextMate has been using exchangedata for atomic saving. This API allows writing an updated file to a new location and then swap the data part atomically with the old file’s. This ensures that the saved file is never in a partially written state, it preserves all file metadata (of which there is a lot), it preserves the file’s inode, so any potential hardlinks are not broken, etc.

Unfortunately APFS, the new default file system for macOS, does not support exchangedata.

TextMate falls back on rename when exchangedata is unavailable.

This require that all metadata of the old file be copied to the new one, but there is no way to preserve the inode, so hardlinks will break, furthermore, as this is effectively a completely new file, the date of its parent diretory will be updated. Some software will monitor directories for new files and do a rescan each time the directory is updated, which previously would only be when files were created or deleted, but now each save may also trigger such rescan.

For this reason, there is a new setting to control when and how TextMate should use atomic saving. It can be controlled by setting atomicSave in .tm*properties to one of the following values:


Many settings can be specified per folder and even per file type, here are the default values:

exclude = "{*.{o,pyc},Icon\r,CVS,*darcs,*MTN,\{arch\},blib,*~.nib}"
include = "{.tm*properties,.htaccess}"

TM*HG  = "/opt/local/bin/hg"
TM*GIT = "/opt/local/bin/git"

[ "/usr/include/{**/,}*" ]
tabSize = 8

[ *.{txt,md,mdown,markdown} ]
softWrap = true

[ .git/COMMIT*EDITMSG ]
softWrap         = true
spellChecking    = true
spellingLanguage = 'en'

[ *.{icns,ico,jpg,jpeg,m4v,nib,pdf,png,psd,pyc,rtf,tif,tiff,xib} ]
binary           = true

[ source.ruby ]
softTabs         = true
tabSize          = 2

[ "/System/Library/Frameworks/**/Headers/**/*" ]
encoding         = "MACROMAN"

[ "{README,INSTALL,LICENSE,TODO}" ]
fileType         = "text.plain"

Load Order

It will read from current folder and up until either it reaches ~ or /. If it reaches / then it will additionally read ~/.tm*properties. This means you can have “global” settings in that file and they work even when opening stuff not under your home folder.

In the file you can do sections with a glob against full path to restrict the following settings to just those which match the glob.

In the variable part you have a few variables, the usual $TM*FILEPATH and friends, but you also have $CWD, this is the folder containing the property file. This is useful if you put a .tm*properties file in the root of your project, for example I use this file with TextMate:

# Settings
tabSize              = 3
projectDirectory     = "$CWD"
windowTitle          = "$TM*DISPLAYNAME — ${CWD/^.*\///}"
excludeInFileChooser = "{$exclude,*.xib}"

# Variables
TM*ORGANIZATION*NAME = 'MacroMates'

TM*SYS*HEADER*PATH   = '${TM*SYS*HEADER*PATH:?$TM*SYS*HEADER*PATH:/usr/include/c++/4.0.0:/usr/include:/System/Library/Frameworks}:$CWD/Shared/include:${BUILD*DIR:-$CWD/build}/TextMate/public'
TM*TODO*IGNORE       = '/(disabled(-src)?|onig-.*|build|cache|CxxTest|(FScript|BWToolkitFramework).framework)/'

TM*MAKE*FILE         = '${CWD}/Makefile'
TM*MAKE*TARGET       = 'TextMate/run'

[ target ]
fileType         = "source.tm-properties"

[ *.{h,pch} ]
fileType         = "source.objc++"

[ Makefile.- ]
fileType         = "source.makefile"

[ attr.untitled ]
fileType         = 'source.c++'

[ "tests/*.{cc,mm}" ]
scopeAttributes  = 'attr.test.cxxtest'
TM*MAKE*TARGET   = '${TM*FILEPATH/^.*?([^\/]*)\/tests\/.*$/$1/}/test'

[ "rmate/*" ]
TM*MAKE*TARGET   = rate

[ vendor/MASPreferences/**/*.{m,h} ]
tabSize      = 4
softTabs     = true
TM*C*POINTER = " *"

As you can see I set the Makefile via CWD — here I can’t use TM*FILEPATH or similar, because those will be the “current file”, not the project root.

Some things of interest is how e.g. test files get the scope augmented, this is because I have unit test snippets I only want active in test files. Additionally I change the make target for test files.

While the .tm*properties can contain both settings and environment variables, while interpreting the file, TextMate doesn’t distingish between the two, so it is possible to mix them in the value part and also reference already set variables, e.g. if we want to extend the default exclude setting we can do:

exclude = '{$exclude,*.o}'

The value is a glob so we use brace expansion to add the *.o extension.


The following is a quick list of issues that should be doable without too much familiarity with the codebase and which do not require “design discussions” per se (in random order):

An older item (still somewhat relevant):

  1. Implement OakTabTriggerImage

    This should be an NSImage subclass which simply renders a tab trigger. It would be used in the menus and bundle item selector (and probably, also bundle editor).

    Making it an NSImage subclass should allow embedding it in attributed strings. This is what we use for the menu items, since it isn’t really possible to augment menu rendering in Cocoa. (The only workaround is to replace the full item with a custom view.)

    For how to do this, check out the implementation of OakFileIconImage.mm.


  1. irc://irc.freenode.net/#textmate  ↩︎