Created
March 29, 2018 17:51
-
-
Save OdatNurd/0b69ee70f8b1a5bc1bcddd11b8c28fa5 to your computer and use it in GitHub Desktop.
Allows placement of Sublime snippet overrides in the User folder, automatically creating empty overrides to mask the packaged version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sublime | |
import sublime_plugin | |
import os | |
import textwrap | |
# Related Reading: | |
# https://forum.sublimetext.com/t/overriding-default-latex-snippet-in-user-folder-not-working/35900 | |
# Sometimes a package (including those shipped with Sublime) contains snippets | |
# that a user would like to alter; for example to match their own code style. | |
# | |
# Although this is possible with a package override, doing so requires you to | |
# recreate your overrides on all machines where you use Sublime, which is an | |
# extra step that could get out of sync. | |
# | |
# Placing your customized snippets in your User package mitigates this problem | |
# but brings with it the problem of having all such snippets appear twice, once | |
# in the User package and once in the original package. | |
# | |
# This plugin helps with this situation by allowing you to place snippet | |
# overrides directly into the User package using the same structure as you | |
# would use for a regular override. | |
# | |
# When executed, the plugin finds all snippets in the User package that mimic a | |
# snippet in another package and will create an empty override for that | |
# snippet, which will cause Sublime to ignore the packaged version of the | |
# snippet. | |
# | |
# As written here, this occurs every time the plugin is loaded and also when | |
# you execute the command, which could be added to the command palette or a | |
# menu entry as desired. | |
# | |
# To use it, move all of your snippet overrides into your User package or | |
# create new ones there, then drop the plugin into your User package. Note that | |
# to work the snippet must appear in the User package exactly as it appears | |
# in the original package. For example: | |
# | |
# Packages/User/Python/Snippets/for.sublime-snippet | |
# | |
# Keep in mind that in use the empty snippets this creates will block the | |
# original package snippets, even if the original package is updated. For this | |
# reason you may want to use OverrideAudit so that you can detect when this | |
# is happening. OverrideAudit is available from: | |
# https://packagecontrol.io/packages/OverrideAudit | |
def plugin_loaded(): | |
""" | |
Runs the custom command at every plugin load (e.g. at Startup) to keep | |
everything up to date; could optionally do this only if there is a setting | |
set, or remove it entirely to require more direct action. | |
""" | |
_update_user_snippet_overrides() | |
def _create_empty_snippet(res_path, override_path): | |
""" | |
Try to create an empty snippet file at the provided path; returns the | |
success or failure of the operation and also displays a message about the | |
operation to the console for tracing purposes. | |
""" | |
try: | |
os.makedirs(os.path.split(override_path)[0], exist_ok=True) | |
open(override_path, 'a').close() | |
print("{plugin}: Created empty snippet for '{file}'".format( | |
plugin=__name__, file=res_path)) | |
return True | |
except Exception as error: | |
print(textwrap.dedent(""" | |
{plugin}: Error creating empty snippet for '{file}': | |
{plugin}: {err}""").lstrip().format( | |
plugin=__name__, file=res_path, err=error)) | |
return False | |
def _update_user_snippet_overrides(): | |
""" | |
Treats the User package as if it was the Packages folder and finds all | |
snippets whose path and name exactly match a snippet in an external | |
package. | |
For each snippet, if there is not already an unpacked version of that | |
snippet, a new empty file is created as a package override, blocking | |
Sublime from seeing the base snippet in favor of the version in the User | |
package instead. | |
This allows you to override snippets from other packages by placing the | |
overrides directly in your User package, to make syncing your | |
customizations between multiple computers easier. | |
""" | |
all_snippets = {file[file.index('/')+1:] for | |
file in sublime.find_resources("*.sublime-snippet")} | |
user_snippets = {file[file.index('/')+1:] for | |
file in all_snippets if file.startswith("User/")} | |
overrides = user_snippets & all_snippets | |
update = 0 | |
error = 0 | |
for snippet in overrides: | |
snippet_path = os.path.join(sublime.packages_path(), snippet) | |
if not os.path.exists(snippet_path): | |
if _create_empty_snippet(snippet, snippet_path): | |
update += 1 | |
else: | |
error += 1 | |
if update or error: | |
sublime.message_dialog(textwrap.dedent(""" | |
Message from: {plugin} | |
Created empty overrides for User package snippets: | |
Created: {update} | |
Failed: {error} | |
See the console for details. | |
""").lstrip().format(plugin=__name__, update=update, error=error)) | |
class CheckUserSnippetOverridesCommand(sublime_plugin.ApplicationCommand): | |
""" | |
Simple user facing command that executes the plugin manually at the user's | |
request. | |
""" | |
def run(self): | |
_update_user_snippet_overrides() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment