Sublime Forum

Doubts about plugin settings

#1

Hello, everybody.

I’m developing a plugin (github.com/elomarns/auto-encoding-for-ruby), and I have two doubts about creating settings for my plugin:

1- The plugin settings file has to be named as Preferences.sublime-settings? Any other name I give seems to have no effect.
2- How do I create a user settings file for my plugin? I did the following on Main.menu:


  {
    "caption": "Preferences",
    "mnemonic": "n",
    "id": "preferences",
    "children":
    
      {
        "caption": "Package Settings",
        "mnemonic": "P",
        "id": "package-settings",
        "children":
        
          {
            "caption": "Auto Encoding for Ruby",
            "children":
            
              {
                "command": "open_file",
                "args": { "file": "${packages}/Auto Encoding for Ruby/Preferences.sublime-settings" },
                "caption": "Settings – Default"
              },
              {
                "command": "open_file",
                "args": { "file": "${packages}/User/Auto Encoding for Ruby.sublime-settings" },
                "caption": "Settings – User"
              },
              {
                "command": "open_file_settings",
                 "caption": "Settings – Syntax Specific – User"
              }
            ]
          }
        ]
      }
    ]
  }
]

But this file doesn’t seems to be loaded. Any settings there returns none when I try to get it with view.settings().get().

Thank in advance.

1 Like

Preferences get lost using the API
Get settings only once
Field markers in plugins development
#2

Your menu file looks fine to me. The filename should be “Main.sublime-menu” in your plugin directory. Be sure to restart Sublime when in doubt. I’ve written a few notes about plugins and settings.

Here’s what I’ve gathered about settings for plugins.

First, if a setting isn’t loading after creating a new setting file, restart Sublime. It has automatic detection when settings files are modified, but doesn’t seem to always notice when new settings files are created.

Settings files are loaded in a specific order. This is documented here: sublimetext.com/docs/2/settings.html, though the documentation could stand some more detail (I created a plugin-oriented list below).

It’s important to understand that there are essentially two separate chains of settings. There are settings that you can manually load (via sublime.load_settings), and then there is the settings tree that is part of Sublime itself (accessed via view.settings). How you handle this depends on how flexible or simple you want your settings to be. I’ve seen plugins use a variety of different techniques.

[size=150]Manual Plugin Settings[/size]
One method is to manually load the settings. I’ll use a plugin named “MyPlugin” as an example. Default settings for your plugin go into your plugin directory, for example:

MyPlugin/MyPlugin.sublime-settings: { "some_value": "foo" }

And OS-specific default settings use Sublime’s regular file naming convention, for example for OSX:

MyPlugin/MyPlugin (OSX).sublime-settings: { "some_value": "osx" }

Which will override values with the same name in the base settings file. Now, you need to explicitly load your settings. Something like this will be appropriate:

settings = sublime.load_settings('MyPlugin.sublime-settings') settings.get('some_value')

The user can override these settings by placing a settings file in their “User” directory with your plugin name. You can either instruct the user to do this via documentation, or by adding a “Package Settings” menu item (described below). Oddly a user cannot specify a platform-specific settings file. This would look like this:

User/MyPlugin.sublime-settings: { "some_value": "user override" }

To review, the order that these are loaded (last match wins):

  1. MyPlugin/MyPlugin.sublime-settings

  2. MyPlugin/MyPlugin ().sublime-settings

  3. User/MyPlugin.sublime-settings

[size=150]Sublime Settings[/size]
Alternatively (or in addition, see below), you can put your settings into Sublime’s normal settings chain. Just beware that this is a flat namespace shared with Sublime and all other plugins, so I recommend using setting names that are unique to your plugin. These are accessed via view.settings().

This has some very good benefits over the previous technique of manually loading settings files. This takes advantage of the full Sublime settings chain, so you can have syntax-specific settings, project-specific settings, etc.

I do not recommend using a nested dictionary for all settings, because if the user wants to override just some settings, they would have to copy the entire dictionary (it won’t flatten nested dictionaries). Just prefix settings names with them with something unique, like your plugin name.

One way to define your defaults using just this technique is to use the “Base File” syntax-specific settings file. This will only work well with TextCommand plugins, because it requires a view to fetch the settings. Other plugin types could use window.active_view.settings(), just beware that active_view will be None if there are no files open (I’m not sure, there may be other scenarios). This is also undocumented (according to the release notes, it sounds like this is included for backwards compatibility with Sublime 1. I don’t really know the whole story.)

MyPlugin/Base File.sublime-settings: { "MyPlugin.example": "base" }

Now you can define syntax-specific defaults, too:

MyPlugin/Python.sublime-settings: { "MyPlugin.example": "python" }

The user can override these globally (User/Base File), per-syntax, or per-project. The order that things would be searched would be (last match wins):

  1. Packages/MyPlugin/Base File.sublime-settings

  2. Packages/MyPlugin/Base File .sublime-settings

  3. Packages/User/Base File.sublime-settings

  4. Packages/User/Preferences.sublime-settings

  5. Project Settings

  6. Packages/MyPlugin/.sublime-settings

  7. Packages/MyPlugin/ .sublime-settings

  8. Packages/User/.sublime-settings

  9. Packages/User/Distraction Free.sublime-settings

And, just FYI, Packages/Default/Preferences.sublime-settings (and platform variants) sit towards the top of the list. I’ve also excluded Buffer settings, which I believe are at the bottom.

[size=150]Combined Method[/size]
Another option is to combine manually loaded settings, and the Sublime settings. You could do this if for some reason the view-only settings don’t work for you (as described above), or you want to have more control over the order that settings are loaded, or you’re uncomfortable using the undocumented “Base File”. Just write a function or whatever that will first try from one, and then the other. For example:

# This is just an example.  Adjust as desired.
settings = sublime.load_settings('MyPlugin')
def get_setting(name, default=None):
	v = settings.get(name)
	if v == None:
		try:
			return sublime.active_window().active_view().settings().get(name, default)
		except AttributeError:
			# No view defined.
			return default
	else:
		return v

I’m not sure this is really worth it, but I figured I’d mention it.

[size=150]Menus[/size]
If your plugin has settings, it would be nice to provide menu options to make it easy for the user to see them (hopefully your base defaults have comments explaining the options) and let them know how to change them. Just include a Main.sublime-menu file in your plugin. There are many plugins out there that do this, just put your entries in Preferences/Package Settings/MyPlugin. Look around for some examples.

[size=150]Final Notes[/size]
I haven’t discussed keymaps or mousemaps. They should be straightforward, though.

Hopefully this helps, and hopefully it’s all accurate. :smile: If anyone else has any thoughts about this, feel free to chime in.

2 Likes

#3

Thank you for your detailed answer!

I was really stuck on this, but with your instructions I’ve achieved what I want using the combined approach.

0 Likes