├── .sublime ├── Default.sublime-commands ├── Default.sublime-keymap └── Main.sublime-menu ├── Plist.hidden-tmTheme ├── Plist.py ├── README.md ├── changelog └── install.txt ├── messages.json ├── popups ├── header.html ├── help.css ├── help.html ├── info.css └── info.html └── syntax └── Plist.sublime-syntax /.sublime/Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [{ 2 | "caption": "Packages UI", 3 | "command": "packages_ui" 4 | }] 5 | -------------------------------------------------------------------------------- /.sublime/Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["t"], 4 | "command": "toggle_pack", 5 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}] 6 | }, { 7 | "keys": ["r"], 8 | "command": "renderlist", 9 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}] 10 | }, { 11 | "keys": ["i"], 12 | "command": "show_info", 13 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}] 14 | }, { 15 | "keys": ["+"], 16 | "command": "change_font_size", 17 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}], 18 | "args": {"plus": true} 19 | }, { 20 | "keys": ["-"], 21 | "command": "change_font_size", 22 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}], 23 | "args": {"plus": false} 24 | }, { 25 | "keys": ["0"], 26 | "command": "change_font_size", 27 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}], 28 | "args": {"plus": "reset"} 29 | }, { 30 | "keys": ["?"], 31 | "command": "toggle_popup_help", 32 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}] 33 | }, { 34 | "keys": ["h"], 35 | "command": "open_homepage", 36 | "context": [{"key": "selector", "operator": "equal", "operand": "text.plist"}] 37 | } 38 | ] -------------------------------------------------------------------------------- /.sublime/Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [{ 2 | "caption": "Preferences", 3 | "mnemonic": "n", 4 | "id": "preferences", 5 | "children": 6 | [ 7 | { 8 | "caption": "Packages UI", 9 | "mnemonic": "P", 10 | "id": "packages-ui", 11 | "command": "packages_ui" 12 | } 13 | ] 14 | }] -------------------------------------------------------------------------------- /Plist.hidden-tmTheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Notebook 7 | settings 8 | 9 | 10 | settings 11 | 12 | background#212121 13 | caret#d3d0c8 14 | foreground#d3d0c8 15 | invisibles#EAE3C9 16 | lineHighlight#353535 17 | selection#000000 18 | popupCss 19 | 23 | 24 | 25 | 26 | name 27 | help symbol 28 | scope 29 | punctuation.definition.help.symbol 30 | settings 31 | 32 | foreground 33 | #5A5EF8 34 | fontStyle 35 | 36 | 37 | 38 | 39 | name 40 | help title 41 | scope 42 | punctuation.definition.help.title 43 | settings 44 | 45 | foreground 46 | #AFAFAF 47 | fontStyle 48 | 49 | 50 | 51 | 52 | name 53 | enabled bullet 54 | scope 55 | punctuation.definition.bullet.enabled.pack 56 | settings 57 | 58 | foreground 59 | #3D916B 60 | fontStyle 61 | bold 62 | 63 | 64 | 65 | name 66 | enabled name 67 | scope 68 | punctuation.definition.pack.name.enabled 69 | settings 70 | 71 | foreground 72 | #3D916B 73 | fontStyle 74 | bold 75 | 76 | 77 | 78 | name 79 | disabled bullet 80 | scope 81 | punctuation.definition.bullet.disabled.pack 82 | settings 83 | 84 | foreground 85 | #B4B4B4 86 | fontStyle 87 | 88 | 89 | 90 | 91 | name 92 | disabled name 93 | scope 94 | punctuation.definition.pack.name.disabled 95 | settings 96 | 97 | foreground 98 | #B4B4B4 99 | fontStyle 100 | 101 | 102 | 103 | 104 | uuid 105 | FE674D9A-27B3-4A5A-84F7-1CC67BD27531 106 | 107 | 108 | -------------------------------------------------------------------------------- /Plist.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | import re 4 | import zipfile 5 | import json 6 | import os 7 | import webbrowser 8 | 9 | bullet_enabled = '✔' 10 | bullet_disabled = '☐' 11 | reg = r"\s{4}(?:("+bullet_enabled+"|"+bullet_disabled+"))(\s)(.+?(?=\s{5,}))(\s+)(\s|\|)(\s+)(?:("+bullet_enabled+"|"+bullet_disabled+"))(\s)(.+?(?=\s{3,}))" 12 | 13 | class ChangeFontSizeCommand(sublime_plugin.WindowCommand): 14 | def run(self, plus): 15 | plistView = None 16 | window = sublime.active_window() 17 | for view in window.views(): 18 | vset = view.settings() 19 | if vset.get("plist.interface") == 'plist': 20 | plistView = view 21 | if plistView: 22 | if plus == 'reset': 23 | return plistView.settings().set("font_size", 12) 24 | 25 | oldSize = plistView.settings().get("font_size") 26 | newSize = oldSize + (1 if plus else -1) 27 | if newSize < 4 or newSize > 20: 28 | return 29 | plistView.settings().set("font_size", newSize) 30 | 31 | class PackagesUiCommand(sublime_plugin.WindowCommand): 32 | def run(self): 33 | plistView = None 34 | window = sublime.active_window() 35 | for view in window.views(): 36 | vset = view.settings() 37 | if vset.get("plist.interface") == 'plist': 38 | plistView = view 39 | 40 | if plistView: 41 | window.focus_view(plistView) 42 | else: 43 | plistView = self.create_view() 44 | 45 | plistView.run_command("renderlist") 46 | 47 | def create_view(self): 48 | view = self.window.new_file() 49 | 50 | view.settings().set('color_scheme', "Packages/PackagesUI/Plist.hidden-tmTheme") 51 | view.settings().set("plist.interface", 'plist') 52 | view.settings().set('highlight_line', True) 53 | view.settings().set("line_numbers", True) 54 | view.settings().set("font_size", 12) 55 | view.settings().set("spell_check", False) 56 | view.settings().set("scroll_past_end", False) 57 | view.settings().set("draw_centered", False) 58 | view.settings().set("line_padding_bottom", 2) 59 | view.settings().set("line_padding_top", 2) 60 | view.settings().set("caret_style", "solid") 61 | view.settings().set("tab_size", 4) 62 | # view.settings().set("rulers", [65, 127]) 63 | view.settings().set("default_encoding", "UTF-8") 64 | view.settings().set("show_minimap", False) 65 | view.settings().set("word_wrap", False) 66 | view.set_syntax_file('Packages/PackagesUI/syntax/Plist.sublime-syntax') 67 | view.set_scratch(True) 68 | view.set_name(bullet_enabled + " Packages UI") 69 | 70 | self.disable_other_plugins(view) 71 | 72 | return view 73 | 74 | 75 | def disable_other_plugins(self, view): 76 | if sublime.load_settings("Plist.sublime-settings").get("vintageous_friendly", False) is False: 77 | view.settings().set("__vi_external_disable", False) 78 | 79 | class RenderlistCommand(sublime_plugin.TextCommand): 80 | def run(self, edit): 81 | print('[Packages UI] render') 82 | self.view.set_read_only(False) 83 | selections = self.view.sel() 84 | full_region = sublime.Region(0, self.view.size()) 85 | self.view.replace(edit, full_region, '') 86 | 87 | sett = sublime.load_settings('Package Control.sublime-settings') 88 | user_s = sublime.load_settings('Preferences.sublime-settings') 89 | 90 | installed_packages = sett.get('installed_packages', []) 91 | ignored_packages = user_s.get('ignored_packages', []) 92 | 93 | plistA = [] 94 | 95 | for index, pack in enumerate(installed_packages): 96 | nshan = bullet_disabled if pack in ignored_packages else bullet_enabled 97 | pname = u" {nshan} {packName}".format(packName=pack, nshan=nshan) 98 | nameLen = len(pname) 99 | space = " "*(60-int(nameLen)) 100 | e = "\n" if (index + 1) % 2 == 0 else " |" 101 | l = u"{pname}{space}{e}".format(pname=pname,space=space, e=e) 102 | plistA.append(l) 103 | 104 | self.view.insert(edit, 0, "".join(plistA)) 105 | 106 | header = sublime.load_resource("Packages/PackagesUI/popups/header.html") 107 | header += "\n" + "="*127 + "\n" 108 | self.view.insert(edit, 0, header) 109 | self.view.set_read_only(True) 110 | 111 | pt = self.view.text_point(3, 0) 112 | self.view.sel().clear() 113 | self.view.sel().add(sublime.Region(pt)) 114 | self.view.show(pt) 115 | 116 | def replace_last(source_string, replace_what, replace_with): 117 | head, _sep, tail = source_string.rpartition(replace_what) 118 | return head + replace_with + tail 119 | 120 | class TogglePackCommand(sublime_plugin.TextCommand): 121 | def run(self, edit): 122 | packs = [] 123 | for cursor in self.view.sel(): 124 | pack = None 125 | (row,col) = self.view.rowcol(cursor.begin()) 126 | leftPack = col < 66; 127 | line_regions = self.view.lines(cursor) 128 | for line_region in line_regions: 129 | string = self.view.substr(line_region) 130 | match = re.match(reg, string) 131 | if not match: 132 | continue 133 | pack = match.group(3 if leftPack else 9) 134 | nshan = bullet_disabled if match.group(1 if leftPack else 7) == bullet_enabled else bullet_enabled 135 | 136 | if leftPack: 137 | string = string.replace(match.group(1 if leftPack else 7), nshan, 1) 138 | else: 139 | string = replace_last(string, match.group(1 if leftPack else 7), nshan) 140 | 141 | if pack and pack not in packs: 142 | packs.append(pack) 143 | self.toggle(pack, self.view) 144 | self.view.set_read_only(False) 145 | self.view.replace(edit, line_region, string) 146 | self.view.set_read_only(True) 147 | 148 | def toggle(self, pack, view): 149 | user_s = sublime.load_settings('Preferences.sublime-settings') 150 | ignored_packages = user_s.get('ignored_packages', []) 151 | 152 | if pack in ignored_packages: # disabled 153 | ignored_packages.remove(pack) 154 | else: 155 | ignored_packages.append(pack) 156 | 157 | save_list_setting(user_s, 'Preferences.sublime-settings', "ignored_packages", ignored_packages) 158 | 159 | class openHomepageCommand(sublime_plugin.TextCommand): 160 | def run(self, edit): 161 | view = self.view 162 | popupCont = [] 163 | packs = [] 164 | for cursor in view.sel(): 165 | pack = None 166 | (row,col) = view.rowcol(cursor.begin()) 167 | leftPack = col < 66; 168 | line_regions = view.lines(cursor) 169 | for line_region in line_regions: 170 | string = view.substr(line_region) 171 | match = re.match(reg, string) 172 | if not match: 173 | continue 174 | pack = match.group(3 if leftPack else 9) 175 | 176 | if pack and pack not in packs: 177 | info = getPackInfo(pack) 178 | url = info.get('url', False) 179 | if url: 180 | webbrowser.open_new_tab(url) 181 | 182 | 183 | class showInfoCommand(sublime_plugin.TextCommand): 184 | def run(self, edit): 185 | view = self.view 186 | popupCont = [] 187 | packs = [] 188 | for cursor in view.sel(): 189 | pack = None 190 | (row,col) = view.rowcol(cursor.begin()) 191 | leftPack = col < 66; 192 | line_regions = view.lines(cursor) 193 | for line_region in line_regions: 194 | string = view.substr(line_region) 195 | match = re.match(reg, string) 196 | if not match: 197 | continue 198 | 199 | pack = match.group(3 if leftPack else 9) 200 | 201 | if pack and pack not in packs: 202 | info = getPackInfo(pack) 203 | infoToShow = [ 204 | "

Name:   " + pack + "

", 205 | "

Version: " + info.get('version', '') + "

", 206 | "

" + info.get('description', '') + "

" 207 | ] 208 | packs.append(pack) 209 | popupCont.append("".join(infoToShow)) 210 | 211 | if popupCont: 212 | css = sublime.load_resource("Packages/PackagesUI/popups/info.css") 213 | html = sublime.load_resource("Packages/PackagesUI/popups/info.html").format(css=css, content="
".join(popupCont)) 214 | view.show_popup(html, 0, -1, max_width=500, max_height=600, on_navigate=webbrowser.open_new_tab) 215 | 216 | class TogglePopupHelpCommand(sublime_plugin.TextCommand): 217 | def run(self, edit, view_name = "help"): 218 | css = sublime.load_resource("Packages/PackagesUI/popups/help.css") 219 | html = sublime.load_resource("Packages/PackagesUI/popups/" + view_name + ".html").format(css=css) 220 | self.view.show_popup(html, 0, -1, max_width=600, max_height=600) 221 | 222 | def save_list_setting(settings, filename, name, new_value, old_value=None): 223 | new_value = list(set(new_value)) 224 | new_value = sorted(new_value, key=lambda s: s.lower()) 225 | 226 | if old_value is not None: 227 | if old_value == new_value: 228 | return 229 | 230 | settings.set(name, new_value) 231 | sublime.save_settings(filename) 232 | 233 | def getPackInfo(package): 234 | package_location = os.path.join(sublime.installed_packages_path(), package + ".sublime-package") 235 | 236 | if not os.path.exists(package_location): 237 | package_location = os.path.join(os.path.dirname(sublime.packages_path()), "Packages", package) 238 | 239 | with open(os.path.join(package_location, "package-metadata.json")) as pack: 240 | data = json.load(pack) 241 | return data 242 | 243 | if not os.path.isdir(package_location): 244 | return False 245 | 246 | if package_location: 247 | with zipfile.ZipFile(sublime.installed_packages_path() + '/' + package + '.sublime-package', "r") as z: 248 | file = z.read('package-metadata.json') 249 | d = json.loads(file.decode("utf-8")) 250 | return d 251 | return False 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Packages UI 2 | ================ 3 | 4 | This plugin provides you a comfortable interface for Sublime Text packages 5 | 6 | Sometimes it might be useful to know which packages are enabled or disabled and also get some short information about every single package. For that purpose you can use Packages UI. This is a very simple and easy tool that helps you to control (enabled/disabled) your plugins. 7 | 8 | ## Usage 9 | 10 | Preferences -> Packages UI 11 | 12 | **NOTE:** Use your mouse or up and down arrows to navigate in list of packages 13 | 14 | [t] toggle package 15 | 16 | [h] open home page 17 | 18 | [i] show info 19 | 20 | [r] refresh view 21 | 22 | [+] increase font size 23 | 24 | [-] decrease font size 25 | 26 | [0] reset font size 27 | 28 | [?] help 29 | 30 | 31 | 32 | ## Screenshots 33 | 34 | ![Demo](https://raw.githubusercontent.com/unknownuser88/PackagesUI/demo/images/demo1.gif) 35 | 36 | ![Pack Info](https://raw.githubusercontent.com/unknownuser88/PackagesUI/demo/images/packs_info1.jpg) 37 | 38 | -------------------------------------------------------------------------------- /changelog/install.txt: -------------------------------------------------------------------------------- 1 | Packages UI 2 | =============================== 3 | 4 | If you like this plugin, "Star" it on ---> https://github.com/unknownuser88/PackagesUI <--- 5 | 6 | This plugin provides you a comfortable interface for Sublime Text packages 7 | 8 | Sometimes it might be useful to know which packages are enabled or disabled and also get some short information about every single package. For that purpose you can use Packages UI. This is a very simple and easy tool that helps you to control (enabled/disabled) your plugins. 9 | 10 | ## Usage 11 | 12 | Preferences -> Packages UI 13 | 14 | NOTE: Use your mouse or up and down arrows to navigate in list of packages 15 | 16 | [t] toggle package 17 | [h] open home page 18 | [i] show info 19 | [r] refresh view 20 | [+] increase font size 21 | [-] decrease font size 22 | [0] reset font size 23 | [?] help -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "changelog/install.txt" 3 | } -------------------------------------------------------------------------------- /popups/header.html: -------------------------------------------------------------------------------- 1 | ====================== [t] toggle package [r] refresh view 2 | PACKAGES [h] open home page [?] help 3 | ====================== [i] show info -------------------------------------------------------------------------------- /popups/help.css: -------------------------------------------------------------------------------- 1 | h2 { 2 | margin-top: 0; 3 | } 4 | h3 { 5 | margin-top: 5px; 6 | margin-bottom: 5px; 7 | } 8 | ul { 9 | margin: 0; 10 | padding: 5px 20px 20px; 11 | } 12 | -------------------------------------------------------------------------------- /popups/help.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 |

Keyboard Shortcuts

7 | 8 |

Actions

9 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /popups/info.css: -------------------------------------------------------------------------------- 1 | html{ 2 | background-color:#000000 3 | } 4 | body{ 5 | background-color:#000000 6 | } 7 | .mainTitle{ 8 | font-size:20px; 9 | font-weight: bold; 10 | padding: 5px 155px; 11 | margin:0 0 10px 0; 12 | } 13 | 14 | .row{ 15 | margin: 0; 16 | padding: 0px 20px 17 | } 18 | .title{ 19 | font-size:15px; 20 | } 21 | .desc{ 22 | font-size:12px; 23 | color:#B0A7FF; 24 | padding:0 20px 25 | } 26 | .val{ 27 | font-size:15px; 28 | color:#BDBDBD; 29 | padding:0 5px 30 | } 31 | .version{ 32 | font-size:13px; 33 | } 34 | .hInfo{ 35 | font-size:11px; 36 | color:#A24141 37 | } -------------------------------------------------------------------------------- /popups/info.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 |
Info
7 | {content} 8 |
9 |
10 |

* Click on package name to open home page

11 | 12 | 13 | -------------------------------------------------------------------------------- /syntax/Plist.sublime-syntax: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | --- 3 | name: Plist 4 | hidden: true 5 | file_extensions: 6 | - plist 7 | scope: text.plist 8 | contexts: 9 | main: 10 | - match: '(\[)([A-Za-z\,\.\-\?\+\-\/]+)(\])' 11 | scope: meta.item.pack.help 12 | captures: 13 | 2: punctuation.definition.help.symbol 14 | 15 | - match: '\s{4}(?:(✔))(\s)(.+?(?=\s{3,}))' 16 | scope: meta.item.pack.name.enabled 17 | captures: 18 | 1: punctuation.definition.bullet.enabled.pack 19 | 3: punctuation.definition.pack.name.enabled 20 | - match: '\s{4}(?:(☐))(\s)(.+?(?=\s{3,}))' 21 | scope: meta.item.pack.name.disabled 22 | captures: 23 | 1: punctuation.definition.bullet.disabled.pack 24 | 3: punctuation.definition.pack.name.disabled 25 | --------------------------------------------------------------------------------