12. 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.
12.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. (Note you will have to close it and re-open
it to remove the “read-only” state of the View.)
If you want to OVERRIDE that menu completely, you can simply do
a File ‣ Save, and it will save it in <data_path>/pkg_name/
directory, creating the directory if necessary to do so. Beware of doing this
however: it will forever after override the entire menu file in the parent Package,
including if it is the Default Package, which would prevent updates to that menu
file with subsequent updates to Sublime Text.
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 (or a directory for the applicable
Package) 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.
12.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 JSONC 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.
12.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"
}
},
]
}
]
}
]
},
12.4. Dynamically Changing Menu Items
Dynamic Menu-Item state can be implemented by overriding certain inherited methods in
the Command class the menu item is associated with (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 |
12.5. Customizing Existing Menu Items
Looking at Tools ‣ Command Palette ‣ View Package File ‣
Default/Main.sublime-menu you will note that some menu items have an "id" entry.
These menu items can be referenced later in order to change them or add to their
children. If a menu item does not have this "id" entry, it is not customizable.
Given the above-mentioned restrictions about having to match both the STRUCTURE and
the SEQUENCE in the default Main.sublime-menu file, specifying the menu item’s
"id" exactly allows you to edit its other properties, including caption, mnemonic
and children. [4]
The limitation with children is that you can only ADD to Sublime Text’s
existing menu items. You cannot change them unless they have an associated
ID. The only way around this is to save the entire default (or Package) menu
file in the Override Package. This practice is generally not
recommended for the Default/Main.sublime-menu file because when
Sublime Text is updated, it would continue to override the main menu
file such that new or modified menu items would not appear.
12.6. Controlling Menu Item Locations in Existing Menus
Generally, when creating new menu items, you reference the existing parent menu
by its "id" value (recreating the structure and sequence of the menu tree as
covered above) and then create a single “children” entry with a list. Whatever you
put in this list gets generally added at the bottom of the menu. This is normally
what you want.
In extreme cases, however, you may wish to change the meaning of existing menu items
that do not have an "id" entry or remove menu items, etc.. To do this,
you Tools ‣ Command Palette ‣ View Package File ‣
<pkg_name>/<menu_name>.sublime-menu and then File ‣ Save in order
to save it in an Override Package under the <data_path> directory.
You will need to close the file and re-open it to remove the “read-only” attribute of
the View. At this point, the entire menu can be modified.
This practice is generally not recommended for menu files, however, because when
the source Package gets updated, an updated menu file in that Package would continue
to be overridden by your file. So the recommended practice is to create a
User/<menu_name>.sublime-menu file so that it ADDS to existing menus instead,
thus not blocking menu updates by the Package author.
12.7. 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.
12.8. 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"
}
]
12.9. 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.
12.10. Further Reading
See https://www.sublimetext.com/docs/menus.html and https://docs.sublimetext.io/reference/menus.html for more details.