├── Default.sublime-commands ├── LICENSE.txt ├── Main.sublime-menu ├── README.md ├── SyntaxMgr.sublime-settings └── syntaxmgr.py /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Syntax Manager: Reload Settings", 4 | "command": "syntax_mgr_reload" 5 | }, 6 | { 7 | "caption": "Syntax Manager: Edit Settings", 8 | "id": "syntax_settings", 9 | "command": "edit_settings", "args": 10 | { 11 | "base_file": "${packages}/SyntaxManager/SyntaxMgr.sublime-settings", 12 | "user_file": "${packages}/User/SyntaxMgr.sublime-settings", 13 | "default": "{\n \"syntaxmgr_settings\":[\n {\n\n }\n ]\n}" 14 | } 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Randy Lai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Preferences", 4 | "id": "preferences", 5 | "children": 6 | [ 7 | { 8 | "caption": "Syntax Manager", 9 | "id": "syntax_settings", 10 | "command": "edit_settings", "args": 11 | { 12 | "base_file": "${packages}/SyntaxManager/SyntaxMgr.sublime-settings", 13 | "user_file": "${packages}/User/SyntaxMgr.sublime-settings", 14 | "default": "{\n \"syntaxmgr_settings\":[\n {\n\n }\n ]\n}" 15 | } 16 | } 17 | ] 18 | } 19 | ] 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Syntax Manager for Sublime Text 2/3 2 | 3 | It helps in applying settings to given syntaxes and extensions. 4 | 5 | I don't understand why Sublime Text makes it so difficult to apply the same setting across several different syntaxes. 6 | For example, if someone want to enable `auto_match_enabled` for `python` and `c`, they has to create two files: 7 | - `Packages/User/Python.sublime-settings` 8 | - `Packages/User/C.sublime-settings` 9 | 10 | Then, in each of the files, add: 11 | 12 | "auto_match_enabled": true 13 | 14 | 15 | This plugin makes it easier by considering following setting in Syntax Manger: 16 | 17 | 18 | "syntaxmgr_settings": [ 19 | { 20 | "scopes": ["source.c", "source.python"], 21 | "settings": { 22 | "auto_match_enabled" : true 23 | } 24 | } 25 | ] 26 | 27 | ## Installation 28 | 29 | Package Control! 30 | 31 | ## Usage 32 | 33 | Open `Preference` -> `Syntax Manager`. Below is a sample of what you can specify in the settings file. 34 | For each item, you need to provide at least one of the filters 35 | 36 | - `scopes` 37 | - `scopes_excluded` 38 | - `extensions` 39 | - `platforms` 40 | - `hostnames` 41 | - `first_line_match` 42 | 43 | ```js 44 | { 45 | "syntaxmgr_settings": [ 46 | { 47 | // platforms, can be osx, windows or linux 48 | "platforms": ["linux", "windows"], 49 | "settings": { 50 | "font_size" : 14 51 | } 52 | }, 53 | { 54 | // match a specific computer based on hostname 55 | // the hostname can be found by running 56 | // 57 | // import platform 58 | // platform.node() 59 | // 60 | // at sublime console (ctrl + ` ) 61 | // 62 | "hostnames": ["some-hostname"], 63 | "settings": { 64 | "font_size" : 12 65 | } 66 | }, 67 | { 68 | // multiple filters can be applied to the same item 69 | "platforms": ["linux", "windows"], 70 | "hostnames": ["some-hostname"], 71 | "settings": { 72 | "font_size" : 12 73 | } 74 | }, 75 | { 76 | // apply this setting when first line matches 77 | "first_line_match": ["#!/.*?/sh"], 78 | "settings": { 79 | // the syntax can be identified by running 80 | // 81 | // view.settings().get("syntax") 82 | // 83 | // at sublime console (ctrl + ` ) 84 | // 85 | "syntax" : "Packages/ShellScript/Shell-Unix-Generic.tmLanguage" 86 | } 87 | }, 88 | { 89 | // the scope of the document can be obtained by pressing 90 | // cmd+alt+p (mac) or ctrl+alt+shift+p (linux / windows) 91 | 92 | // for c and python files 93 | "scopes": ["source.c", "source.python"], 94 | "settings": { 95 | "trim_trailing_white_space_on_save_scope" : true, 96 | "auto_match_enabled" : true 97 | } 98 | }, 99 | { 100 | // all text files 101 | "scopes": ["text"], 102 | "settings": { 103 | "spell_check": true, 104 | "color_scheme": "Packages/Color Scheme - Default/Twilight.tmTheme" 105 | } 106 | }, 107 | { 108 | // use latex syntex for these extensions 109 | // make sure the syntax is applied first and then the settings 110 | "extensions": ["ltx", "latex", "l"], 111 | "settings": { 112 | "syntax": "Packages/LaTeX/LaTeX.tmLanguage" 113 | } 114 | }, 115 | { 116 | // for all text files, excluding latex files 117 | "scopes": ["text"], 118 | "scopes_excluded": ["text.tex"], 119 | "settings": { 120 | "spell_check": false 121 | } 122 | } 123 | ] 124 | } 125 | ``` 126 | 127 | ### Reload Settings 128 | 129 | Occasionally, syntax manager may fail to apply settings automatically, 130 | especially when creating new file. Reloading syntax manger will be helpful in 131 | this situation. To reload settings, launch comment palette (`C+shift+p`) and type "Syntax Manager: Reload Settings". 132 | -------------------------------------------------------------------------------- /SyntaxMgr.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "syntaxmgr_settings": [ 3 | { 4 | // visit https://github.com/randy3k/SyntaxManager for an exmaple 5 | } 6 | ] 7 | } -------------------------------------------------------------------------------- /syntaxmgr.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | import re 4 | import platform 5 | 6 | 7 | class SyntaxMgrCriteria(): 8 | def __init__(self, S): 9 | self.S = S 10 | 11 | def apply(self, view): 12 | settings = self.S.get("settings", []) 13 | for key, value in settings.items(): 14 | view.settings().set(key, value) 15 | 16 | def match_scopes(self, view): 17 | scopes = self.S.get("scopes", []) 18 | scopes = [scopes] if isinstance(scopes, str) else scopes 19 | scopes_excluded = self.S.get("scopes_excluded", []) 20 | scopes_excluded = [scopes_excluded] if isinstance(scopes_excluded, str) else scopes_excluded 21 | 22 | return (not scopes or any([view.score_selector(0, s) > 0 for s in scopes])) \ 23 | and all([view.score_selector(0, s) == 0 for s in scopes_excluded]) 24 | 25 | def match_extensions(self, view): 26 | extensions = self.S.get("extensions", []) 27 | extensions = [extensions] if isinstance(extensions, str) else extensions 28 | 29 | if not extensions: 30 | return True 31 | 32 | fname = view.file_name() 33 | extensions = ["." + e for e in extensions] 34 | return fname and fname.lower().endswith(tuple(extensions)) 35 | 36 | def match_platform(self, view): 37 | platforms = self.S.get("platforms", []) 38 | platforms = [platforms] if isinstance(platforms, str) else platforms 39 | 40 | if not platforms: 41 | return True 42 | 43 | return sublime.platform() in [p.lower() for p in platforms] 44 | 45 | def match_firstline(self, view): 46 | firstlinepat = self.S.get("first_line_match", self.S.get("firstline", "")) 47 | firstlinepat = [firstlinepat] if isinstance(firstlinepat, str) else firstlinepat 48 | 49 | if not firstlinepat: 50 | return True 51 | 52 | for pat in firstlinepat: 53 | first_line = view.substr(view.line(view.text_point(0, 0))) 54 | if re.match(pat, first_line): 55 | return True 56 | 57 | return False 58 | 59 | def match_hostname(self, view): 60 | hostnames = self.S.get("hostnames", []) 61 | hostnames = [hostnames] if isinstance(hostnames, str) else hostnames 62 | 63 | if not hostnames: 64 | return True 65 | 66 | return platform.node() in hostnames 67 | 68 | def match(self, view): 69 | return self.match_scopes(view) and self.match_extensions(view) and \ 70 | self.match_platform(view) and self.match_firstline(view) and self.match_hostname(view) 71 | 72 | 73 | class SyntaxMgrListener(sublime_plugin.EventListener): 74 | 75 | def load_syntax_mgr(self, view): 76 | if view.settings().get('is_widget'): 77 | return 78 | 79 | if view.size() == 0 and not view.file_name(): 80 | return 81 | 82 | if not view.settings().has("syntax_mgr_loaded"): 83 | view.settings().set("syntax_mgr_loaded", True) 84 | view.run_command("syntax_mgr_reload") 85 | 86 | def on_new(self, view): 87 | # need a small delay here to give he view a chance to prepare 88 | # itself 89 | sublime.set_timeout(lambda: self.load_syntax_mgr(view), 0) 90 | 91 | def on_load(self, view): 92 | self.load_syntax_mgr(view) 93 | 94 | def on_activated(self, view): 95 | self.load_syntax_mgr(view) 96 | 97 | 98 | class SyntaxMgrReload(sublime_plugin.TextCommand): 99 | def run(self, edit): 100 | view = self.view 101 | settings = sublime.load_settings('SyntaxMgr.sublime-settings') 102 | for s in settings.get("syntaxmgr_settings", []): 103 | criteria = SyntaxMgrCriteria(s) 104 | if criteria.match(view): 105 | criteria.apply(view) 106 | --------------------------------------------------------------------------------