也许这是另一轮“静态vs实例”,但我试图在细节上做个恶魔。 请注意,我是Python和插件开发的新手。
某些插件使用以下代码:
s = sublime.load_settings(__name__ + '.sublime-settings')
class Settings:
def load(self):
self.setting1 = s.get('setting1', 'default1')
self.setting2 = s.get('setting2', 'default2')
...
# Global Scope
settings = Settings()
settings.load()
s.add_on_change(__name__ + '-reload', settings.load)
此示例没有什么特别的错误,除了load_settings
和add_on_change
方法应属于Settings
:
class Settings:
def __init__(self):
self.settings = sublime.load_settings(__name__ + '.sublime-settings')
self.settings.add_on_change(__name__ + '-reload', self.setup)
self.setup()
def setup():
self.setting1 = self.settings.get('setting1', 'default1')
self.setting2 = self.settings.get('setting2', 'default2')
...
# Global Scope
settings = Settings()
现在Settings
类封装了所有功能。
但我们真的需要这个类的实例吗?
我不这么认为。
这就是为什么static
应该被使用的原因:
class Settings:
settings = sublime.load_settings(__name__ + '.sublime-settings')
@staticmethod
def init():
Settings.settings.add_on_change(__name__ + '-reload', Settings.setup)
Settings.setup()
@staticmethod
def setup():
Settings.setting1 = Settings.settings.get('setting1', 'default1')
Settings.setting2 = Settings.settings.get('setting2', 'default2')
...
# Global Scope
Settings.init()
上述示例的优点(如果有)是:
有没有其他“体面”的方式来组织设置?
答案 0 :(得分:0)
您的第二个示例是最好的方法,所有内容都封装在一个类中。 @staticmethod
方法没有我能想到的优点-一次只创建一个实例的类完全没有错。
应从settings = Settings()
内部调用全局plugin_loaded()
分配,以确保ST API准备就绪,否则sublime.load_settings(FILENAME)
可能会失败。
应使用回调,以便如果用户更改设置,则无需重新启动Sublime Text即可更新设置的值。如果用户卸载了插件,应在plugin_unloaded()
中将其删除。
这是一个来自我的插件的粗略模板。它应该是一个很好的开始,可以将设置处理添加到Sublime Text插件中。
此GitHub Gist中的代码。
import sublime
import sublime_plugin
# The global scope ensures that the settings can
# be easily accessed from within all the classes.
global settings
def plugin_loaded():
"""
This module level function is called on ST startup when the API is ready.
"""
global settings
settings = Settings()
settings.load_all()
def plugin_unloaded():
"""
This module level function is called just before the plugin is unloaded.
"""
settings.remove_callbacks()
class Settings:
"""
Handles all the settings. A callback method is added for each setting, it
gets called by ST if that setting is changed in the settings file.
"""
def __init__(self):
FILENAME = "YourPluginName.sublime-settings"
self.settings = sublime.load_settings(FILENAME)
# User configurable settings.
self.max_display_length = None
self.monospace_font = None
self.ellipsis_symbols = None
self.prefix_custom = None
self.command_names = None
# ...
def load_all(self):
self.init_setting("max_display_length", self.set_max_display_length)
self.init_setting("monospace_font", self.set_monospace_font)
self.init_setting("ellipsis_symbols", self.set_ellipsis_symbols)
self.init_setting("prefix_custom", self.set_prefix_custom)
self.init_setting("command_names", self.set_command_names)
# ...
def init_setting(self, setting_name, setting_method):
"""
Calls the setting_method to set the setting's value and registers the
setting_method as a callback so that it will be called by ST if the
setting's value is changed by the user.
"""
setting_method()
self.settings.add_on_change(setting_name, setting_method)
def remove_callbacks(self):
self.settings.clear_on_change("max_display_length")
self.settings.clear_on_change("monospace_font")
self.settings.clear_on_change("ellipsis_symbols")
self.settings.clear_on_change("prefix_custom")
self.settings.clear_on_change("command_names")
# ...
# Methods for the user configurable settings.
def set_max_display_length(self):
DEFAULT = 70
MIN_LENGTH = 50
value = self.integer_setting("max_display_length", DEFAULT, MIN_LENGTH)
self.max_display_length = value
def set_monospace_font(self):
DEFAULT = True
value = self.boolean_setting("monospace_font", DEFAULT)
self.monospace_font = value
def set_ellipsis_symbols(self):
DEFAULT = "…"
value = self.string_setting("ellipsis_symbols", DEFAULT)
self.ellipsis_symbols = value
def set_prefix_custom(self):
DEFAULT = ""
# This setting may be set to a string or a list of strings;
# if it is a list then ensure all list elements are strings.
value = self.list_or_string_setting("prefix_custom", DEFAULT)
if isinstance(value, list):
for index, item in enumerate(value):
if not isinstance(item, str):
value[index] = str(item)
self.prefix_custom = value
def set_command_names(self):
DEFAULT = []
value = self.list_setting("command_names", DEFAULT)
self.command_names = value
# Methods for settings retrieval; all will return a
# setting of the required type or the default value.
def string_setting(self, setting, default):
return self.setting_of_type(setting, default, str)
def list_setting(self, setting, default):
return self.setting_of_type(setting, default, list)
def boolean_setting(self, setting, default):
return self.setting_of_type(setting, default, bool)
def list_or_string_setting(self, setting, default):
return self.setting_of_type(setting, default, (str, list))
def setting_of_type(self, setting, default, required_type):
value = self.settings.get(setting, None)
return value if isinstance(value, required_type) else default
# Special case.
def integer_setting(self, setting, default, min_value):
value = self.settings.get(setting, None)
return value if self.is_integer(value) and value >= min_value else default
def is_integer(self, value):
# Bool is a subclass of int; isinstance(False, int) == True.
return isinstance(value, int) and not isinstance(value, bool)
答案 1 :(得分:-1)
除非您有充分的理由,否则不要使用“命名”设置文件。
将您的设置放在程序包根目录中的Preferences.sublime-settings
文件中。这些设置将由Sublime Text自动加载并合并到默认设置中。
使用您的软件包名称前缀所有设置,然后使用.
为默认设置消除歧义,例如phpunit.composer
,phpunit.keymaps
。
考虑以下Preferences.sublime-settings
{
"phpunit.composer": true,
"phpunit.keymaps": true
}
用户现在可以全局或按项目设置它们。
全局设置:Preferences > Settings
{
"phpunit.composer": false
}
或按项目:Project > Edit Project
{
"settings": {
"phpunit.composer": false
}
}
通过视图对象自动提供设置:
view = sublime.active_window().active_view()
settings = view.settings()
is_composer_enabled = settings.get('phpunit.composer')
您仍然可以直接通过偏好文件获取它们:
settings = sublime.load_settings('Preferences.sublime-settings')
is_composer_enabled = settings.get('phpunit.composer')
您也可以在keymap文件中使用它们,例如启用/禁用键盘映射:
{
"keys": [",", "a"],
"command": "phpunit_test_suite",
"context": [{ "key": "setting.phpunit.keymaps" } ]
}
请勿使用“已命名”设置文件。使用命名设置文件的方法太多了。我认为使用命名设置文件的惯例是一个非常糟糕的约定,它需要停止。它会导致各种问题,需要很多样板代码才能使它们正常工作,有些情况下你甚至无法做某些事情,比如在keymap文件中使用它们。
您可以找到我的PHPUnitKit插件中使用的设置示例。