SublimeText / sublime_lib

Utility library for frequently used functionality in Sublime Text and convenience functions or classes
https://sublimetext.github.io/sublime_lib
MIT License
52 stars 4 forks source link

Settings listener classes #164

Open Thom1729 opened 3 years ago

Thom1729 commented 3 years ago

As seen on Discord. Motivating examples:

from sublime_lib import GlobalSettingsListener, ViewSettingsListener, on_setting_changed

class TabSizeListener(ViewSettingsListener):
    @classmethod
    def is_applicable(cls, settings: sublime.Settings) -> bool:
        return settings.get('translate_tabs_to_spaces', False)

    @classmethod
    def applies_to_primary_view_only(cls) -> bool:
        return True

    @on_setting_changed('tab_size')
    def tab_size_changed(self, new_value: object, old_value: object) -> None:
        self.view.run_command('resize_existing_tabs', {
            'new_size': new_value,
            'old_size': old_value,
        })

class JsCustomConfigurationsListener(GlobalSettingsListener)
    SETTINGS_NAME = 'JS Custom.sublime-settings'

    @on_setting_changed(get_configurations)
    def configurations_changed(self, new_configurations, old_configurations):
        if not self.settings.get('auto_build', False):
            return

        changed = [
            name for name in set(old_configurations) | set(new_configurations)
            if old_configurations.get(name, None) != new_configurations.get(name, None)
        ]

        if changed:
            print('JS Custom: Configuration changed. Rebuilding some syntaxes.')
            sublime.active_window().run_command('build_js_custom_syntaxes', {'versions': changed})

This would provide the same convenience features as SettingsDict.subscribe: selecting the desired value from the settings, detecting whether that value has changed, and keeping track of the previous value. What is also provides beyond that is automatic management of the subscription lifetime. Manually calling clear_on_change is annoying, easy to forget, prone to mistakes, and when done right kind of boilerplate-y. A SettingsListener class can handle this automatically by simply inheriting from the existing listener classes (that Sublime already manages), calling clear_on_change in __del__, and using a weakref in add_on_change.

FichteFoll commented 3 years ago

Do we want to ensure the decorator is only used on classes that subclass our SettingsListener classes or would that hinder mixin usage?

Can we even? I think at the time the decorator is called, the function hasn't been bound to the class yet, so that might be a moot point.