.. include:: /include/substitutions.txt .. include:: /include/external_links.txt .. include:: /include/custom_roles.txt .. _menus: ***** Menus ***** Sublime |nbsp| 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 :term:`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 |nbsp| Text :term:`GUI`. (Some keyboards also have the ability to open Context Menus.) The objects in Sublime |nbsp| Text that can host a Context Menu are (Context Menu names are in parentheses): - :term:`Sheets ` - Views (Context) - Images (Image Context) - Tabs (Tab Context) - :term:`Side Bar` - OPEN FILES list (Tab Sidebar Context) - FOLDERS - :term:`Mount Points ` (Side Bar Mount Point) - Folders and Files, possible multiple items selected (Side Bar) - :term:`Status Bar` - Encoding Status (Encoding) - Line Ending Status (Line Endings) - Indentation Status (Indentation) - Current Syntax Status (Syntax) - :term:`Overlay Panels ` - Console (Console Input Widget) - Find-in-Files Panel (Find in Files) - Other :term:`input panels ` (Widget Context) Each Menu's content can be found (and customized) in :term:`Package Resource` files named: ``.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 |nbsp| 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. Customizing Menus ***************** If you haven't already done so, go ahead and open Sublime |nbsp| 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 :term:``/Packages/Default/ but if you look on your file system, you will find that there is no such directory! That's because Sublime |nbsp| Text uses that file from :term:``/Packages/Default.sublime-package which contains that file internally and shows it to you as if it was in the :term:``/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 |nbsp| Text, you must create a valid JSON file in your :term:``/Packages/User/ directory using the EXACT same file name. Example: ``Main.sublime-menu``. If you use any other file name, Sublime |nbsp| Text ignores it, since the file name is how Sublime |nbsp| 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-menu`` file, or else Sublime |nbsp| Text will silently not show them. Menu-Item Structure ******************* Menus in Sublime |nbsp| 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 :term:``/Packages/User/ directory. Menus use :term:`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: .. code-block:: json [ { "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 |nbsp| Text knows about. (You can create new commands using :doc:`plugins`.) If Sublime |nbsp| 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. 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 |nbsp| 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 |nbsp| Text developers decide to change or restrict that behavior. Example to add to the ``Preferences > Package Settings`` sub-menu: .. code-block:: json { "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" } }, ] } ] } ] }, Dynamically Changing Menu Items ******************************* Dynamic Menu-Item state can be implemented by overriding certain inherited methods in the :term:`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 | ``is_enabled(self)`` returning ``False`` | ``True`` | +----------------------+------------------------------------------------+-----------------+ | hiding Menu Item | ``is_visible(self)`` returning ``False`` | ``True`` | +----------------------+------------------------------------------------+-----------------+ | adding a check mark | ``is_checked(self)`` returning ``True`` | ``False`` | +----------------------+------------------------------------------------+-----------------+ | changing its caption | ``description(self)`` returning caption string | empty string | +----------------------+------------------------------------------------+-----------------+ Menu Items are also disabled when the Command is associated with a Key Binding, and the Key Binding's :term:`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. 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 ``files`` argument, 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 ``dirs`` argument, 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 ``paths`` argument, it will receive an array containing the full path of each file and directory that was selected when the right-click was performed. 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 :term:`Buffer` is not stored on disk). Example: .. code-block:: json [ { "caption": "Your Copy Path", "command": "copy_path" } ] 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. Further Reading *************** See https://www.sublimetext.com/docs/menus.html and https://docs.sublimetext.io/reference/menus.html for more details.