Sublime Forum

Having settings data available to all commands

#1

What’s a suitable way to have the data from a .sublime-settings file available to all the commands of a package/plugin without having to go to each command and getting individual settings data and converting them to globals ?

0 Likes

#2

I write functions to get settings and import it whenever I need to. I assumed that there is only one settings file in my plugin.

settings.py

def get_setting(dotted: str, default: Optional[Any] = None) -> Any:
    """
    @brief Get the plugin setting with the dotted key.

    @param dotted  The dotted key
    @param default The default value if the key doesn't exist

    @return The setting's value.
    """

    return dotted_get(get_settings_object(), dotted, default)


def get_settings_file() -> str:
    """
    @brief Get the settings file name.

    @return The settings file name.
    """

    return "YOUR PLUGIN'S SETTINGS FILENAME"  # such as "my.sublime-settings"


def get_settings_object() -> sublime.Settings:
    """
    @brief Get the plugin settings object.

    @return The settings object.
    """

    return sublime.load_settings(get_settings_file())


def dotted_get(var: Any, dotted: str, default: Optional[Any] = None) -> Any:
    """
    @brief Get the value from the variable with dotted notation.

    @param var     The variable
    @param dotted  The dotted
    @param default The default

    @return The value or the default if dotted not found
    """

    keys = dotted.split(".")

    try:
        for key in keys:
            if isinstance(var, (dict, sublime.Settings)):
                var = var.get(key)
            elif isinstance(var, (list, tuple, bytes, bytearray)):
                var = var[int(key)]
            else:
                var = getattr(var, key)

        return var
    except Exception:
        return default

Example usage:

// my.sublime-settings
{
    "a": {
        "b": {
            "c": "hello",
        }
    }
}
from ..settings import get_setting  # depends on the relative path

get_setting("a.b.c", "valueNotFound")  # "hello"
get_setting("a.b.c.d", "valueNotFound")  # "valueNotFound"
get_setting("a.b.d", "valueNotFound")  # "valueNotFound"
1 Like

#3

Out of curiosity, why do you want/need globals for your settings? sublime.load_settings() caches the resulting settings object and changes made to settings elsewhere are reflected in the settings object when you ask for a setting.

The paradigm that I tend to use is something like the following, which results in a single function call that fetches the settings and ensures a default value if the settings file is missing something (though you could leave that out entirely if desired). Things get more complicated if you also want to fetch data from the user preferences though.

def plugin_loaded():
    """
    On plugin load, cache the settings object for our package.
    """
    gz_setting.obj = sublime.load_settings("GZipper.sublime-settings")
    gz_setting.default = {
        "unzip_on_load": True,
        "compression_level": 9,
        "trash_temp_on_close": True,
        "delete_on_trash_fail": False
    }

def gz_setting(key):
    """
    Get a package setting from the cached settings object with a sensible
    default.
    """
    default = gz_setting.default.get(key, None)
    return gz_setting.obj.get(key, default)
2 Likes

#4

I really should try to phrase my questions in a way that would help a majority of the viewers and also me but sometimes I get carried away with my needs :slightly_smiling_face: In my case, I have actually got the settings data in the run method so far for all the commands and then used them in some later method after calling a bunch of show_quick_panel()/show_input_panel() to get user data. I don’t think I can do that without using globals unless I call sublime.settings(...) in that specific method, but then I thought there must be a way to refactor the code to share the settings data among commands (to get a single source of truth so as to speak) for better codebase maintenance. Hence the question & confusion.

0 Likes

#5

I write a class to store those global variable like caches and states. And again import it when I need it with from .Globals import global_get, global_set.

0 Likes