Building a SublimeText command from scratch (and other useful bits)
Note: Since I started writing this, SublimeText3 came out. Hopefully I’ve caught any problems ST3 has with my methods.
SublimeText is my current text editor of choice. While I use a few others for specific tasks1, if I’m just going to chuck words in a file I’ll probably find myself using Sublime Text. One of the nice things about ST is the extensive plugin framework: a series of python files in a pretty simple file hierarchy makes for a bunch of hackability.
A while back I decided to make a ST plugin for collecting markdown reference links. I know that this plugin exists in a number of packages, but for whatever stubborn reason I didn’t want to install someone else’s scripts, I wanted to do it myself. While I found a couple of tutorials on the web for this task, there was nothing that really told me everything I wanted to know, so I had to muddle through it myself. Now I know what’s going on, I figure I should write this down, either to help others in their quest to write ST plugins, or simply for future reference.
The many sections of a SublimeText plugin
A basic SublimeText plugin looks like this:
import sublime, sublime_plugin
//code goes in here
This is a really, really bare-bones plugin. If you save this to SublimeText’s
Packages directory (available via
Preferences>Browse Packages...), or into a folder within this directory2, it’ll get scanned and added to ST’s list of commands (assuming you save it with the
Note: this is not the same as having it pop up in the Command Palette (that is, the menu you get when you his
⌘+⇧+P). As it stands, you can run your plugin by opening up SublimeText’s console (
^+`) and typing
command_name is equal to the name of the class you just created, in
snake_case. If your plugin ends with
Command, leave that off. So
FooPlugin would be
FooCommand would just be
foo. I’ll go over how to put this in the command palette and make pretty shortcuts for it later on - for the moment we’ll just run it through the command palette.
You’ll note that this is a text command. It’s possible to make other commands, but I have the most experience with text commands, so I’ll stick with them for now.
There’s only a few other methods that SublimeText plugins take. The main one that’s of use is the
This method tells you if a given plugin is enabled. If it’s not, it won’t show up in the command palette ever and generally won’t run. It’s handy because you can combine it with some pretty nifty in-program logic:
return self.view.settings().get('syntax') == 'Packages/Markdown/Markdown.tmLanguage'
This plugin will only run when your syntax is set to Markdown.
Retrieving bits of the document
This is all good only if we can do something in our plugin. Thankfully, SublimeText has a pretty good API for this sort of thing. I think you can do a lot with just getting the document’s contents, scanning through it, and making modifications based on simple logic, so I’m going to go through some of the commands for doing just that.
Most text-related commands are contained within SublimeText’s
view object, accessible in text commands via
self.view. As an example, if you want to search the document for a particular string, you can use the
You can do similar things with
find_all, which will grab all instances of the string. The string also accepts regular expressions, which is handy.
Regions, which are basically a set of beginning and ending positions. A number of
view methods will take regions as arguments, so sometime you just have to pass it from one place to another; if you want to start poking around inside it, the above-mentioned API reference has a pretty good guide to its methods.
Modifying the document
All modifications to a SublimeText document are done within a given
Edit. When you undo a change, it undoes all the work of the last edit. This means if you make a command that does fifteen find-and-replaces in your document, but does these all under the one
Edit, when you undo that last command it’ll undo all fifteen find-and-replaces.
You can make your own
Edit objects if you want to split your command into a number of bits3, but really, most of the time you can just use the edit that gets passed into the
Let’s make a command that will replace every instance of the word “FOO” with “BAR”, as a simple example:
import sublime, sublime_plugin
for region in self.view.find_all("FOO"):
self.view.replace(edit, region, "BAR")
The only new thing here is calling
self.view.replace. This replaces a given region with a string. We wrap this all up in the one edit command.
Between these examples and the API, you should be able to make your command do what you want with the document. It may require some fiddling around, but hopefully you now have enough tools to do a bunch of fiddling and go from there.
So far, your best way of getting to the command is through SublimeText’s control panel. Which, let’s face it, isn’t very user-friendly. You can access most commands through:
- The command palette, and sometimes also
- A key binding
The command palette is populated on a by-syntax basis. If you’re currently using language foo on a file, then you’ll get commands that are defined in
Default.sublime-commands (mine is in the
Default folder in the plugins directory), and those defined in any files called
.py files, SublimeText seems to find
sublime-commands files wherever they are in your plugin hierarchy.
sublime-commands files are JSON files that have the following syntax:
"caption": "What you see in the command palette",
Generally, I make sure my commands are available via the command palette. Since the command palette is filtered by language, and fuzzy-text searching is ridiculously fast, it doesn’t matter if you stick ten extra commands in there.
This is the best way of accessing commands that you use all the time. However, it does require another set of files.
First, you need to put your key bindings in a file called “Default.sublime-keymap”.4 You can’t call it “
This is also a JSON file, and the layout looks something like this:
"keys" : ["super+i"],
This is a simple keybinding that maps
super+i (which is ⌘+i on OS X, Ctrl+i on Windows/Linux) to a little snippet. Now, wherever you are, you can type
super+i and have your text italicised.
If you don’t want to use the snippet outside of the keybinding, you can always specify it inline with the
"keys" : ["super+i"],
There is a slight problem here - regardless of where you store your keybinding file, this keybinding will work wherever you are. All is not lost, however, since you can limit where key bindings apply with contexts. Here’s an example of a keybinding with a context:
"keys" : ["super+i"],
A context is an array of criteria that need to be fulfilled for Sublime Text to trigger a key binding. A handy list of possible contexts is available here. While the syntax is a little bulky, by using contexts you can ensure that your keybindings only trigger when you want them to.
Packaging and storing
Based on this guide, you should be able to make a series of SublimeText commands, give them applicable names in the comand palette, and assign shortcuts as required. You should also be able to limit the scope in which a command applies, so it doesn’t show up in your command palette (and the keybinding doesn’t trigger) when you don’t want it to. The last thing to do is to store and organise commands in packages.
You can get to your packages directory in SublimeText by selecting
Sublime Text→Preferences→Browse Packages… from the menu. In OS X this is
~/Library/Application Support/Sublime Text 3/Packages. Sublime Text loads files from folders in the package directory in the following order:
- Files in the
- Files in other folders, alphabetically
- Files in the
Files will overwrite previous key bindings, commands, etc. So if you have the key
super+i bound in keymaps in
super+i in SublimeText will trigger the command as specified in
It’s generally good practise to put “miscellaneous” snippets, commands, key bindings etc. in the
User directory, but once you have two or three files for one language you might want to split them off and put them in their own folder. If you want to transfer your files between computers (or share them with others), you can make a
sublime-package file in the following manner:
- Zip up the directory containing your files.
- Change the extension from
You can place this in the
Packages directory and SublimeText will read it as if it were a folder.
But where’s all the default packages?
In Sublime Text 3, the
Packages directory looks practically abandoned compared to ST2. This is because all the default packages are stored alongside the program itself. In OS X you can find the packages inside the app bundle under
MacOS/Packages. These are all stored as
sublime-package files, so if you want to examine the contents of them you just have to make a copy somewhere else, then rename to
.zip and unzip them.
Hopefully at the end of this you can create commands for Sublime Text 3, bind them to the command palette or key combinations, and store them properly. Some of this I’m still learning (and the release of ST3 has meant I’ve had to re-learn some things), but this guide contains most of the stuff I had no luck googling or ended up figuring out by myself. SublimeText’s API reference is pretty robust, so between this guide and the references linked to throughout the article, you should be able to work out how to get SublimeText to do what you want.
But no deeper - ST only checks the
Packagesdirectory, and directories inside of it, for plugins. Anything buried further it ignores. ↩
Details in the API again ↩
You can technically get away with calling it “Default (OSX).sublime-keymap”, “Default (Windows).sublime-keymap” or “Default (Linux).sublime-keymap”, but then presumably it’ll only work on that OS. Handy? Sometimes. ↩