10. Menus
Sublime Text has a number of different menus. All of them can be customized.
The Main Menu is the row of click-able words just under each Window’s
Title Bar. The Main Menu’s default definition can be found in the Default Package’s
Main.sublime-menu file.
Context Menus are a pop-up menus that open as a result of right-clicking any of several objects in the Sublime Text GUI. (Some keyboards also have the ability to open Context Menus.)
The objects in Sublime Text that can host a Context Menu are (Context Menu names are in parentheses):
-
Views (Context)
Images (Image Context)
Tabs (Tab Context)
-
OPEN FILES list (Tab Sidebar Context)
FOLDERS
Mount Points (Side Bar Mount Point)
Folders and Files, possible multiple items selected (Side Bar)
-
Encoding Status (Encoding)
Line Ending Status (Line Endings)
Indentation Status (Indentation)
Current Syntax Status (Syntax)
-
Console (Console Input Widget)
Find-in-Files Panel (Find in Files)
Other input panels (Widget Context)
Each Menu’s content can be found (and customized) in Package Resource files named:
<menu_name>.sublime-menu
The default version of these are in the Default Package, and customizations of
these can be found in various other Packages.
To view them: Tools > Command Palette > View Package File: and type
in “sublime-menu”. This will display a list of all menu resource files known to
Sublime Text.
All of these menus are customizable, but how to do so is neither intuitive, nor is it per the current documentation (or at minimum the current documentation on it is unclear). Here’s how to do it.
10.1. Customizing Menus
If you haven’t already done so, go ahead and open Sublime Text’s default main menu:
Tools > Command Palette > View Package File> type “sublime-menu Main”
to select it, and hit [Enter] to open it.
Notice that it is read only. Also notice that it “appears” to be in the folder
<data_path>/Packages/Default/
but if you look on your file system, you will find that there is no such directory! That’s because Sublime Text uses that file from
<executable_path>/Packages/Default.sublime-package
which contains that file internally and shows it to you as if it was in
the <data_path>/Packages/Default/ directory. You can both copy text from it
into the clipboard as well as perform a File > Save As... on it if you want it
somewhere on your file system, perhaps so you can do searches on it (and other menus)
using Find-in-Files.
To customize any of these menus, like many other customization actions for
Sublime Text, you must create a valid JSON file in your
<data_path>/Packages/User/ directory using the EXACT same file name. Example:
Main.sublime-menu. If you use any other file name, Sublime Text ignores it,
since the file name is how Sublime Text tells what menu you are adding to or modifying.
Once your file is there, you simply add the parts of the menu that you want to add or change. The top-level is always a JSON array object, and its elements are Menu Item JSON objects with the structure shown below.
For context menus (menus that pop-up when you right-click something), whatever menu-item objects you create in your JSON file simply gets added to the bottom of the context menu. For the main menu, however, the structure is a little different:
you only need to include menu items that you want to add, but
you have to match both the STRUCTURE and the SEQUENCE in the default
Main.sublime-menufile, or else Sublime Text will silently not show them.
10.2. Menu-Item Structure
Menus in Sublime Text are defined by files ending in .sublime-menu. As noted
above, the filename must exactly match the default filename of the menu you are
modifying, and be stored in your <data_path>/Packages/User/ directory. Menus
use Sublime-relaxed-JSON format, with the top-level structure being an array.
Each contained object in the array is a “Menu Item”: a JSON object containing
information to define the text and behaviors of the displayed menu entry.
Example:
[
{
"caption": "File",
"mnemonic": "F",
"id": "file",
"children":
[
{ "command": "new_file", "caption": "New File", "mnemonic": "N" },
{ "command": "prompt_open_file", "caption": "Open File…", "mnemonic": "O", "platform": "!OSX" },
{ "command": "prompt_open_folder", "caption": "Open Folder…", "platform": "!OSX" },
{ "command": "prompt_open", "caption": "Open…", "platform": "OSX" }
]
}
]
As you can see, Menu Items can be nested in a tree structure. To carry out an action, “leaf” Menu Items contain “command” elements that lead to commands that Sublime Text knows about. (You can create new commands using Plugins.) If Sublime Text doesn’t know about them, they will be disabled (grayed out).
Supported keys:
- “caption”:
The text of the menu entry.
- “mnemonic”:
The character to use as the key to press to activate the entry. This only applies to Windows and Linux. Must match the case of the character in the “caption”.
- “command”:
A string of the command to execute when the entry is activated.
- “args”:
A JSON object of args to send to the command.
- “children”:
A JSON array of Menu-Item objects, which, when not empty, creates a submenu.
- “id”:
A unique string for the menu entry. This is used for menu entries with “children” to allow others to add additional child entries.
- “platform”:
One of the strings: “OSX”, “!OSX”, “Windows”, “!Windows”, “Linux” or “!Linux”. Controls what platforms the entry is shown on.
Each menu entry requires at minimum, the key “caption” for a non-functionality entry. “command” is required for an entry that performs an action.
Menu Items that have a caption value of “-” will be shown as a divider in the menu.
10.3. Adding to Existing Sub-Menus
To add to an existing sub-menu, you have to “build out” the existing structure using “empty” menu items. To build an “empty” menu item, simply create its structure with the existing “id” key with matching value, and include a “children” element with an array.
Important:
The structure you build has to match both the SEQUENCE and the STRUCTURE of the Main Menu. If you don’t, Sublime Text will silently not show it, and won’t say why.
There is one exception to this: if you create a top-level Menu Item, it will be shown on the right side of the normal (default) top-level Menu Items, no matter where you put it in the structure (so long as it is a top-level Menu Item). It’s probably best to put it last (to match the shown structure) in case the Sublime Text developers decide to change or restrict that behavior.
Example to add to the Preferences > Package Settings sub-menu:
{
"id": "preferences",
"children":
[
{
"id": "package-settings",
"children":
[
{
"caption": "Your Package Name",
"children":
[
{
"caption": "Documentation",
"command": "open_url",
"args": {
"url": "https://your-site.com/YourPackage/"
}
},
{ "caption": "-" },
{
"caption": "Settings",
"command": "edit_settings",
"args": {
"base_file": "${packages}/YourPackage/YourPackage.sublime-settings",
"default": "{\n\t$0\n}\n"
}
},
{ "caption": "-" },
{
"caption": "Key Bindings",
"command": "edit_settings",
"args": {
"base_file": "${packages}/YourPackage/Default ($platform).sublime-keymap",
"default": "[\n\t$0\n]\n"
}
},
]
}
]
}
]
},
10.4. Dynamically Changing Menu Items
Dynamic Menu-Item state can be implemented by overriding certain inherited methods in
the Command class (in whatever Plugin implements it). Command arguments
beyond self are passed as keyword arguments.
Action |
Method to Override |
Inherited Value |
|---|---|---|
disabling Menu Item |
|
|
hiding Menu Item |
|
|
adding a check mark |
|
|
changing its caption |
|
empty string |
Menu Items are also disabled when the Command is associated with a Key Binding,
and the Key Binding’s Selector evaluates to False.
Note
In order for the description(self) method to have an effect, the Menu Item
object in the .sublime-menu file must either:
have a “caption” entry that provides an empty string, or
have no “caption” entry.
10.5. Side Bar “Magic”
If you add your own Menu Items to the Side Bar context menu, you will want to know that you can use certain arguments with your commands:
- “files”: []:
If your command has a
filesargument, it will receive an array containing the full path of each file that was selected when the right-click was performed.- “dirs”: []:
If your command has a
dirsargument, it will receive an array containing the full path of each directory that was selected when the right-click was performed.- “paths”: []:
If your command has a
pathsargument, it will receive an array containing the full path of each file and directory that was selected when the right-click was performed.
10.6. Other Context Menu “Magic”
For all other context menus, calling the command copy_path will receive the full
path of the file in the current View (or None if its Buffer is not stored
on disk).
Example:
[
{
"caption": "Your Copy Path",
"command": "copy_path"
}
]
10.7. Lastly
In case you were not already aware, it is customary (though not required) to add an ellipsis (“...”) to captions whose commands launch a dialog box or open a panel to get information before the command is carried out. That helps the user know that when he clicks Menu Items that do not have this, to expect that the command will be carried out immediately, whereas with Menu Items with the “...”, he can expect some type of intermediate dialog box or panel to show up first before any action is taken.
10.8. Further Reading
See https://www.sublimetext.com/docs/menus.html and https://docs.sublimetext.io/reference/menus.html for more details.