.. include:: /include/substitutions.txt .. include:: /include/external_links.txt .. include:: /include/custom_roles.txt .. _packages: ******** Packages ******** Packages are simply a set of :term:`Resource Files ` used by Sublime |nbsp| Text, gathered into a single directory named after the Package. A Package Resource is simply a :term:`Resource File` that is part of a Package and therefore in a Package directory. Another (more compact) form they can come in (e.g. the shipped Packages and most user-installed Packages are in this form) is in a ``.sublime-package`` file, which is simply a ``.zip`` file containing all the files of that package, preserving the Package's directory structure. Compressed or not, any package file can be viewed using: ``Tools > Command Palette... > View Package File`` Files retrieved from a compressed file will be read-only, but may be saved as editable files using. ``File > Save As...`` (They remain read-only until they are closed and then re-opened again from where they were saved.) Be advised: if there is a ``.sublime-package``, as well as a loose file in a :term:``/Packages// directory, the contents of the loose file will override the ENTIRE file stored in the ``.sublime-package`` file. See `Overriding`_ below for more details. Sublime |nbsp| Text ships with over 50 Packages pre-installed, and many, many user-created Packages are available through several channels, the easiest of which is using the Package Control Package, which provides very easy management of the Packages you have installed with any given Sublime-Text installation. Sublime |nbsp| Text Packages vs Python Packages *********************************************** As it turns out, the name "Package" in Sublime |nbsp| Text's Python context is indeed aptly chosen: Sublime |nbsp| Text indeed "considers" a Sublime |nbsp| Text Package as a Python Package, despite its not having a ``__init__.py`` file in it, which is normally what makes a `Python Package`_ a Package. Rationale: From your Sublime |nbsp| Text Package, you can do relative importing, which is ONLY legal from within a Python Package, and generates an exception when it is used outside of a Python Package. .. code-block:: py from . import sibling_module This is logical actually, since the ``importlib`` package (comes with Python, and is used "under the covers" as the implementation of the ``import`` statement) allows directly importing of Python modules *as packages* whether they have a ``__init__.py`` file in them or not. So I suspect that is the mechanism being used by Sublime |nbsp| Text for "bringing in" individual Python plugins as part of a package named after the parent directory, and is probably also why the :ref:`Sublime Data `/User/ directory is sometimes referred to as the "User Package". And why shouldn't Sublime |nbsp| Text use that powerful mechanism? It's Python's way of making new functionality available safely under its own namespace. Indeed, `API Environments Overview`_ describes the environment Plugins are run in, and the 3rd paragraph hints strongly that it indeed treats a Sublime |nbsp| Text Package as a Python Package. Locations ********* The concept of a "Packages Directory" is really 5 possible locations for any given Package Resource File. :Default Package: Loaded first; ``Default.sublime-package`` [1]_ - Represented location: :term:``/Packages/Default/ - Actual location: :term:``/Packages/ :shipped Packages: Loaded next (alphabetically by Package name); ``.sublime-package`` files shipped with Sublime |nbsp| Text are stored here. (Do not change this directory's contents.) [1]_ - Represented location: :term:``/Packages// - Actual location: :term:``/Packages/ :installed Packages: Loaded next (alphabetically by Package name); Packages installed by user are stored here when they are designed to remain in ``.sublime-package`` format. [1]_ - Represented location: :term:``/Packages// - Actual location: :term:``/Installed Packages/ (not editable) :unpacked Packages: Loaded next (alphabetically by Package name); Packages installed by the user when designed to be unpacked (loose files) by Package Control, as well as user-created Packages can be stored here. - Represented location: :term:``/Packages// - Actual location: same (on disk, Resource files editable) (See note below.) :User Package: Loaded last; /User/. Customizations unique to each user are stored here. Path representation: ``Packages/User/``. - Represented location: :term:``/Packages/User/ - Actual location: same (on disk, Resource files editable) If you are a power user, your customizations will go in the latter 2 directories. The ``User`` Package can be used to develop new packages while they are in experimental stages. Once in a more complete state, they can be moved to ``/Packages//``. .. [1] ``.sublime-package`` files are `.zip` files with the extension renamed. .. _overriding: Overriding ********** The above loading sequence is how "overrides" or customized behavior are implemented. Note carefully that when the Package (including the ``User`` Package) has a file like ``Default (Windows).sublime-keymap`` or ``Main.sublime-menu``, it does not replace the whole Keymap or Main Menu. In these cases, the overriding happens at a finer level of granularity: these files contain JSON data structures (e.g. a list or tree structure [respectively] of dictionary objects), and the value of each entry in the data structure overwrites the already-loaded value for the entry with the same key and hierarchy location in the data structure. So you can think of the contents of both files as being "merged", where due to the loading sequence outlined above, the values loaded from the Packages lower in the list *overwrite* the same values from Packages higher in the list. It is this sequence that governs what overrides what. Note that the above-described "merge" override behavior is what happens between the Package (including the `User` Package) and the Sublime |nbsp| Text application, and is restricted to just *some* (not all) of the :term:`Resource Files ` that contain :term:`Sublime-relaxed-JSON format` data: - .sublime-commands - .sublime-completions - .sublime-keymap - .sublime-menu - .sublime-mousemap - .sublime-settings But this does not apply to any of the other types of :term:`Resource Files `: - .sublime-build - .sublime-color-scheme - .tmTheme - .sublime-macro - .tmPreferences - .py - .sublime-snippet - .sublime-syntax - .tmLanguage - .sublime-theme .. _overriding whole files: Overriding Whole Files from a Zipped Package ============================================ Once you understand the "merge-type" overriding described above, it is important to understand that there is another type of overriding (whole-file overriding) that is triggered when: - the Package being overridden is in archive form (i.e. with ``.sublime-package`` file extension, which will be either an :term:`installed Package` or a :term:`shipped Package`, and - the override file is placed in an unpacked Package directory (i.e. in :term:``/Packages// with an identical relative path and name). In this case, Sublime |nbsp| Text literally ignores that same file from the ``.sublime-package`` file and replaces it with loose file in the unpacked Package directory. In this case, the loose-file directory :term:``/Packages// is called an "Override Package". Illustrated: .. code-block:: text /Packages/Installed Packages/.sublime-package, or /Packages/.sublime-package -----+ | loose file with | same name and | same relative | subdirectory /Packages//... <--------------------------------+ When the Override Package directory is empty, it doesn't change anything. But for each occurrence of a file with the exact same relative subdirectory and filename as in the ``.sublime-package`` file, Sublime Edit ignores the ``.sublime-package`` file and uses the loose file in the Override Package instead. An interesting aspect of Override Packages is that Python plugins therein are able to use relative import paths for accessing other modules in the corresponding ``.sublime-package`` file as if they were part of it. Example: You want to add functionality to the Python Package's ``def`` (function) Snippet. Its default content is provided in :term:``/Packages/Python.sublime-package. The way to find the Snippet file that is involved, make a copy of the ``Python.sublime-package`` file in a safe, empty directory, change its extension to ``.zip`` and then extract the contents out of the file. Scan the package Snippet files for ``def`` or just ``>def<`` and you will find it in the ``./Snippets/`` subdirectory as ``function.sublime-snippet``. Make a copy of that file and place it in :term:``/Packages/Python/Snippets/ then modify it to suit you. Sublime |nbsp| Text reloads it as soon as you save it so the turn-around time on modifications-to-testing is remarkably short. .. note:: The following two Packages provide a convenient way to create an override of a single Package file. The Commands they provide that do this are: - PackageResourceViewer: Open Resource - OverrideAudit: Create Override Both of these commands: - open the file in an editable form, with an "apparent" path :term:``/Packages//, even though that file (and directory) may not exist yet, and - use the `Ctrl+S` (Save file) operation to create the file if it is not already there, as well as create the new :term:``/Packages// directory if it did not already exist. .. note:: Some packages are configured to be installed as loose files in the :term:``/Packages//. When this is the case, once they are installed, the only instance of that Package is as loose files in that directory. When this is the case, editing of those :term:`Package Resource` files (when they are not created by yourself) is not recommended because those files get replaced when the Package is updated. If you wish to override only certain files in an unpacked Package, you can create a ``.sublime-package`` file out of it by zipping its contents, preserving the directory structure under the :term:``/Packages// directory, naming the zipped file .sublime-package and moving the newly-created file into the :term:``/Installed Packages/ directory. Then in the original (unpacked) directory (which now becomes an :term:`Override Package` because of the existence of the ``.sublime-package`` file where Sublime |nbsp| Text will load it), keep only the files you wish to override. .. caution:: A precaution about Override Packages: if/when the overridden file(s) in the corresponding ``.sublime-package`` is updated, you will not be notified. The OverrideAudit package provides monitoring of override files and will notify you when the file it overrides has been updated. Creating New Packages ********************* You create a new package by simply creating a directory under :term:``/Packages/. This directory is conveniently accessible via ``Preferences > Browse Packages...``. A Package's Python Version ========================== As of Sublime |nbsp| Text build 4200, the default Python version used by a package is 3.3. However, Python 3.8 is available. To get your Package to use Python 3.8, place a file in the top directory of the package containing just 3 bytes: "3.8". .. code-block:: text MyPackage/ .python-version .. _managing package complexity: Managing Package Complexity *************************** As functionality is added to Packages being developed, they can become quite complex. (Sometimes they have complex designs to start with.) For increased maintainability (via modularity) it can be useful to move related groups of related functionality into their own Python modules. Simpler Packages can factor out related functionality into their own sibling (top-level) Python modules which make use of each others' facilities via the ``from . import sibling_module`` statement. More complex Packages sometimes factor out related functionality as `Subpackages`_ for the same reason that Python supports Subpackages within Packages: modularity and maintainability---each Subpackage has its own sphere of responsibility. The method of doing this is exactly the same as implementing `Python Subpackages`_. Usually developers will want to limit doing this to when it makes sense to do so: when the subpackage is relatively self-contained, providing its own data and/or services to the main Package, and (preferably) only depending upon external Packages that ship with Python. There is an important caveat to using Subpackages in a Sublime |nbsp| Text Package if you have `Package Control`_ installed (which is true for virtually all Sublime |nbsp| Text installations). The reason for this is that the ``Package Control`` Package automatically updates installed Packages while Sublime |nbsp| Text *is running*, and when it does this, it *does not re-start the Python Interpreter*, but instead uses ``importlib.reload()`` to reload the top-level Python modules (``.py`` files) in each installed Package that gets updated. If an updated Package has Subpackages that might have been updated, those Subpackages *do not* get automatically reloaded (with their possibly-updated logic) until Sublime |nbsp| Text restarts. For Packages that will never change again, this is not an issue. However, for packages that get updated periodically, when the update happens, until Sublime |nbsp| Text is restarted, there is a risk of such Packages being in an inconsistent state and possibly broken *unless the Package itself* addresses this caveat internally. Here is how to do it. Let's say your Package is called ``ProComment`` and is structured like this: .. code-block:: text ProComment/ procomment.py <-- central Plugin lib/ __init__.py debug.py func_parsing.py utils.py src/ __init__.py core.py contexts.py commands/ __init__.py insert_comment.py insert_datestamp.py insert_timestamp.py Your central Plugin is named ``procomment.py`` and you have 3 Subpackages: ``lib``, ``src/`` and ``src/commands/``. In your central Plugin, implement something like this: .. code-block:: py """ procomment.py """ import importlib import sys import os from typing import Tuple # ========================================================================= # Data # ========================================================================= _cfg_compressed_pkg_ext = '.sublime-package' # Use name of parent directory as `package_name`. module_path, _ = os.path.splitext(os.path.realpath(__file__)) parent_dir, submodule_name = os.path.split(module_path) _, package_name = os.path.split(parent_dir) if package_name.endswith(_cfg_compressed_pkg_ext): package_name = package_name[:-len(_cfg_compressed_pkg_ext)] del _ this_module_name = f'{package_name}.{submodule_name}' _reload_indent_level = -1 # Can't use `debugging = is_debugging(DebugBit.IMPORTING)` here because # the import required to support it causes a circular import. debugging = True if debugging: print(f'{this_module_name} >>> module execution') # ========================================================================= # Load / Reload # ========================================================================= def reload(dotted_subpkg: str, submodules: Tuple[str, ...] = ()): """ Reload each module in `submodules` only if previously loaded. This is a precondition of calling ``importlib.reload()`` but is also for efficiency: - if Sublime Text is just starting, nothing important happens here (because the cached modules will not have been added to ``sys.modules`` yet), and and the various ``import`` statements do the loading in the usual way; - if ``Package Control`` is updating this Package (or the central Plugin was just saved during development), then this function recursively reloads each loaded module, and the ``import`` statements then do nothing since each target module will already be in ``sys.modules``. Note: The below works on the basis that ``/Packages`` directory was placed in ``sys.path`` by Sublime Text. So the module names being constructed below have to look like this: MyPackage.subdir.module MyPackage.subdir.subdir.module etc. :param dotted_subpkg: dotted directory portion of module names that will be found in the keys of ``sys.modules``. Example: 'MyPackage.src.commands' :param submodules: list of submodule names """ global _reload_indent_level _reload_indent_level += 1 indent = ' ' * _reload_indent_level if debugging: if _reload_indent_level == 0: print('vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv') print(f'{indent}reload(): >>> {dotted_subpkg=} {submodules=}') if not submodules: # Called from top-level Plugin. module_name = dotted_subpkg if module_name in sys.modules: if debugging: print(f'{indent}Reloading({module_name})') importlib.reload(sys.modules[module_name]) else: # Called from subpackage. for submodule in submodules: module_name = f'{dotted_subpkg}.{submodule}' if module_name in sys.modules: if debugging: print(f'{indent}Reloading({module_name})') importlib.reload(sys.modules[module_name]) if debugging: print(f'{indent}reload(): <<<') if _reload_indent_level == 0: print('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^') _reload_indent_level -= 1 reload(package_name + '.lib') # Recurse into .lib/ subpackage. reload(package_name + '.src') # Recurse into .src/ subpackage. from .lib import * from .src import * # ========================================================================= # Events # ========================================================================= def plugin_loaded(): core.on_plugin_loaded() def plugin_unloaded(): core.on_plugin_unloaded() if debugging: print(f'{this_module_name} <<<') Then in each ``__init__.py`` file for each Subpackage: .. code-block:: py """ lib/__init__.py """ from ..procomment import reload from .debug import IntFlag, DebugBit, is_debugging from .utils import sublime_subpackage_name subpackage_name = sublime_subpackage_name(__file__, 2) debugging = is_debugging(DebugBit.IMPORTING) if debugging: print(f'{subpackage_name} >>> module execution') reload(subpackage_name, ('debug', 'func_parsing', 'utils')) from . import func_parsing from . import utils __all__ = [ 'debugging', 'func_parsing', 'utils' ] if debugging: print(f'{subpackage_name} <<<') .. code-block:: py """ src/__init__.py """ from ..procomment import reload from ..lib.debug import IntFlag, DebugBit, is_debugging from ..lib.utils import sublime_subpackage_name subpackage_name = sublime_subpackage_name(__file__, 2) debugging = is_debugging(DebugBit.IMPORTING) if debugging: print(f'{subpackage_name} >>> module execution') reload(subpackage_name, ('core', 'contexts')) reload(subpackage_name + '.commands') # Recurse into .commands/ subpackage. from . import core from .contexts import * from .commands import * __all__ = [ 'core', # events/contexts "ProCommentContextEventListener", # commands/* "ProCommentInsertDatestampCommand", "ProCommentInsertTimestampCommand", 'ProCommentInsertCommentCommand', ] if debugging: print(f'{subpackage_name} <<<') .. code-block:: py """ src/commands/__init__.py """ from ...procomment import reload from ...lib.debug import IntFlag, DebugBit, is_debugging from ...lib.utils import sublime_subpackage_name subpackage_name = sublime_subpackage_name(__file__, 3) debugging = is_debugging(DebugBit.IMPORTING) if debugging: print(f' {subpackage_name} >>> module execution') reload(subpackage_name, ('insert_datestamp', 'insert_timestamp', 'insert_comment')) from .insert_comment import ProCommentInsertCommentCommand from .insert_datestamp import ProCommentInsertDatestampCommand from .insert_timestamp import ProCommentInsertTimestampCommand __all__ = [ # Comment Commands 'ProCommentInsertCommentCommand', # Datestamp/Timestamp Commands 'ProCommentInsertDatestampCommand', 'ProCommentInsertTimestampCommand', ] if debugging: print(f' {subpackage_name} <<<') where ``sublime_subpackage_name`` is defined in ``.lib/utils.py`` as: .. code-block:: py _cfg_compressed_pkg_ext = '.sublime-package' def sublime_subpackage_name(file_path: str, subpackage_depth: int): module_list = [] working_path, _ = os.path.splitext(file_path) # print(f'>>> Looking for: [{_cfg_compressed_pkg_ext=}]') for i in reversed(range(subpackage_depth + 1)): remaining, submodule = os.path.split(working_path) include = True # print(f'>>> Before: [{submodule=}]') if submodule == '__init__': include = False elif i == 0 and submodule.endswith(_cfg_compressed_pkg_ext): # print(f'>>> Ends with: [{_cfg_compressed_pkg_ext=}]') submodule = submodule[:-len(_cfg_compressed_pkg_ext)] # print(f'>>> After : [{submodule=}]') if include: module_list.append(submodule) working_path = remaining return '.'.join(reversed(module_list)) and produces a return value that looks like: "ProComment.src.commands" based on the physical path contained in ``__file__``---exactly what the ``reload()`` function needs. Note carefully that ``src/__init__.py`` explicitly recursed into the ``src/commands/`` directory like this---after all its modules *at that level* were imported: .. code-block:: py reload(subpackage_name + '.commands') # Recurse into .commands/ subpackage. This then causes a "cascade" of all the modules being reloaded: when ``procomment.py`` gets either loaded (for the first time) or reloaded (by ``Package Control``). The end result of this pattern: - When Sublime |nbsp| Text starts, all Subpackages get loaded via a cascade of ``import`` statements. - When the ``Package Control`` Package updates your Package and reloads the central Plugin (or when you save your central Plugin during development), all the modules in each Subpackage get reloaded via a cascade of ``reload()`` calls. If you would like to verify/trace that visually, you can see the cascade of importing and reloading in the debug output (from the code above) into the Console Panel when Sublime |nbsp| Text is first started: .. code-block:: text reloading plugin ProComment.procomment ProComment.procomment >>> module execution vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.lib' submodules=() reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.src' submodules=() reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ProComment.lib >>> module execution vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.lib' submodules=('debug', 'func_parsing', 'utils') Reloading(ProComment.lib.debug) Reloading(ProComment.lib.utils) reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ProComment.lib <<< ProComment.src >>> module execution vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.src' submodules=('core', 'contexts') reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.src.commands' submodules=() reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ProComment.src.commands >>> module execution vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.src.commands' submodules=('insert_datestamp', 'insert_timestamp', 'insert_comment') reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ProComment.src.commands <<< ProComment.src <<< ProComment.procomment <<< And this is the debug output each time ``procomment.py`` is saved (or when the ``Package Control`` Package updates the package while Sublime |nbsp| Text is running). .. code-block:: text reloading plugin ProComment.procomment ProComment: Plugin unloaded at 23-Feb-2026 11:53 ProComment.procomment >>> module execution vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.lib' submodules=() Reloading(ProComment.lib) ProComment.lib >>> module execution reload(): >>> dotted_subpkg='ProComment.lib' submodules=('debug', 'func_parsing', 'utils') Reloading(ProComment.lib.debug) Reloading(ProComment.lib.func_parsing) Reloading(ProComment.lib.utils) reload(): <<< ProComment.lib <<< reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv reload(): >>> dotted_subpkg='ProComment.src' submodules=() Reloading(ProComment.src) ProComment.src >>> module execution reload(): >>> dotted_subpkg='ProComment.src' submodules=('core', 'contexts') Reloading(ProComment.src.core) Reloading(ProComment.src.contexts) reload(): <<< reload(): >>> dotted_subpkg='ProComment.src.commands' submodules=() Reloading(ProComment.src.commands) ProComment.src.commands >>> module execution reload(): >>> dotted_subpkg='ProComment.src.commands' submodules=('insert_datestamp', 'insert_timestamp', 'insert_comment') Reloading(ProComment.src.commands.insert_datestamp) Reloading(ProComment.src.commands.insert_timestamp) Reloading(ProComment.src.commands.insert_comment) reload(): <<< ProComment.src.commands <<< reload(): <<< ProComment.src <<< reload(): <<< ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ProComment.procomment <<< Debugging: [0x2002] - LOAD_UNLOAD: 0x0002 - IMPORTING : 0x2000 ProComment: Initialized at 23-Feb-2026 11:53. Turn debugging output off, and all of the above happens silently and happily in the background. .. note:: The lines: .. code-block:: text Debugging: [0x2002] - LOAD_UNLOAD: 0x0002 - IMPORTING : 0x2000 is from the ``lib/debug.py`` module as a result of having at least 1 debugging bit turned on at the time the Console output was captured. The line: .. code-block:: text ProComment: Initialized at 23-Feb-2026 11:53. at the end is a result of having the LOAD_UNLOAD debugging bit turned on at the time the Console output was captured. Troubleshooting Packages ************************ Because Sublime |nbsp| Text is so customizable, it is possible for 3rd-party Packages and/or local customization to interfere with one another, or cause other problems. You might see this, for example, as Python exceptions that don't make sense in the Console Panel, or certain functionality isn't behaving as you expect. Safe Mode ========= As of Sublime |nbsp| Text 4, you can now launch Sublime |nbsp| Text in Safe Mode by using this option on the command line to launch it. subl --safe-mode Sublime |nbsp| Text initially displays this dialog box to describe the run-time environment: .. figure:: _static/images/safe_mode_announcement.png :align: center :alt: Screenshot showing Safe Mode Announcement Screenshot showing Safe Mode Announcement When launched this way, Sublime |nbsp| Text uses an alternate :ref:`Data Directory` thus disabling all 3rd-party Packages and local customizations, as well as internally not loading any previous sessions (i.e. from any `.sublime-workspace` files). This will help you to verify whether the behavior is, or is not, coming from Sublime |nbsp| Text itself or one of its shipped Packages. The alternate Data Directory used is: :Windows: ``%APPDATA%/Sublime |nbsp| Text (Safe Mode)/`` :Windows Portable Version: ``path/to/application/Data (Safe Mode)/`` :Linux: ``~/.config/sublime-text-safe-mode/`` :MacOS: ``~/Library/Application Support/Sublime |nbsp| Text (Safe Mode)/`` If the behavior is still being exhibited, it is most likely from a corrupted shipped Package file and can be remedied by re-installing Sublime |nbsp| Text. If the behavior disappears, then you know it was coming from somewhere in the Data Directory. A nice thing about Safe Mode is that you can install experimental customizations or packages you think might have caused problems, and it will not affect Sublime |nbsp| Text's ability to start and behave normally because: - such packages will be installed in the alternate Data Directory, thus not impacting normal sessions, and - each time Sublime |nbsp| Text starts in Safe Mode, it deletes any content in the Safe-Mode Data Directory, so it "doesn't hurt" if a package installed there did something it wasn't supposed to. **Caution:** don't store anything important in the Safe-Mode Data Directory! Diagnosing Trouble from the Data Directory ========================================== If you have reached the conclusion that the trouble you are experiencing has come from the Data Directory (3rd-Party Packages and/or local customization), you can discover the source of the problem by following these steps. Knowing *when* the problem started is also an asset, because the cause will most likely have occurred just before the problem started. - Close Sublime |nbsp| Text if it is running. - Rename the :ref:`Data directory` to another name to keep it as a backup and reference about what Packages you installed and what customizations you made. - Re-start Sublime |nbsp| Text. When Sublime |nbsp| Text starts, it will create a fresh new Data Directory. Note: In subsequent steps, it is recommended to keep the contents of the renamed (backup) of the problematic Data Directory unaltered for sake of preserving the evidence. This is so that if your first attempt at isolating the problem isn't successful, you can repeat it (using smaller or different steps) as many times as needed until you have isolated the problem. Diagnosis by Isolating Packages ------------------------------- Now you can re-install 3rd-Party Packages you had in place (and were working correctly) well before the problem started. Test to verify whether the problem is occurring after this step. - If the problem is *not occurring* at this point, you can continue to diagnose by re-adding each subsequent Package one by one, until the behavior returns, at which point you will know what Package to exclude or disable. - On the other hand, if the problem ***is occurring***, you know the problem is somewhere in that group of Packages, and you can take steps to further isolate the source by reverting and repeating this step with only half of the Packages, and keep dividing the problematic group until you have isolated the source. Diagnosis by Isolating Customizations ------------------------------------- If you have reached this point and the problem has not returned, now you can add your own customizations back in, one at a time, until the problem resurfaces. If/when you encounter the problem again, you will know where to investigate further to remedy, or, as the case may be, what *not* to do. Further Reading *************** The more you know about `Python's Import System `_, the more you will understand some of the power of Sublime Text Packages and their facilities brought to bear by Python itself (e.g. their ability use modular subpackages to cleverly manage Package complexity, and thereby make a Package more understandable, and thereby more maintainable).