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 ?
Having settings data available to all commands
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.
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"
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)
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 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.