├── Default (Linux).sublime-keymap
├── Default (OSX).sublime-keymap
├── Default (Windows).sublime-keymap
├── Default.sublime-commands
├── LICENSE
├── Main.sublime-menu
├── README.md
├── fav.sublime-syntax
├── favorites.py
├── favorites.sublime-settings
├── images
├── commands.png
├── favorites.gif
└── global_vs_project.png
├── messages.json
└── messages
├── 1.0.1.txt
├── 1.0.2.txt
├── 1.0.3.txt
├── 1.0.4.txt
├── 1.0.5.txt
├── 1.0.7.txt
└── install.txt
/Default (Linux).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | ]
3 |
--------------------------------------------------------------------------------
/Default (OSX).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 | ]
3 |
--------------------------------------------------------------------------------
/Default (Windows).sublime-keymap:
--------------------------------------------------------------------------------
1 | [
2 |
3 | ]
4 |
--------------------------------------------------------------------------------
/Default.sublime-commands:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "Favorites: Toggle Visibility",
4 | "command": "show_favorites"
5 | }
6 | ,
7 | {
8 | "caption": "Favorites: Add active view (global)",
9 | "command": "add_favorites"
10 | }
11 | ,
12 | {
13 | "caption": "Favorites: Add active view (project's)",
14 | "command": "add_proj_favorites"
15 | }
16 | ,
17 | {
18 | "caption": "Favorites: Edit favorites (global)",
19 | "command": "edit_favorites_file"
20 | }
21 | ,
22 | {
23 | "caption": "Favorites: Edit favorites (project's)",
24 | "command": "edit_proj_favorites_file"
25 | }
26 | ,
27 | {
28 | "caption": "Favorites: Open all (global)",
29 | "command": "openall_favorites"
30 | },
31 | {
32 | "caption": "Favorites: Open all (project's)",
33 | "command": "openall_proj_favorites"
34 | }
35 | ,
36 | {
37 | "caption": "Favorites: Remove all (global)",
38 | "command": "remove_favorites_file"
39 | },
40 | {
41 | "caption": "Favorites: Remove all (project's)",
42 | "command": "remove_proj_favorites_file"
43 | }
44 | ]
45 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Oleg Shilo
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
11 | all 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
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/Main.sublime-menu:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "Preferences",
4 | "mnemonic": "n",
5 | "id": "preferences",
6 | "children": [
7 | {
8 | "caption": "Package Settings",
9 | "mnemonic": "P",
10 | "id": "package-settings",
11 | "children": [
12 | {
13 | "caption": "Favorites",
14 | "children": [
15 | {
16 | "command": "open_file",
17 | "args": {
18 | "file": "${packages}/Favorites/favorites.sublime-settings"
19 | },
20 | "caption": "Settings – Default"
21 | },
22 | {
23 | "command": "open_file",
24 | "args": {
25 | "file": "${packages}/User/favorites.sublime-settings"
26 | },
27 | "caption": "Settings – User"
28 | }
29 | ]
30 | }
31 | ]
32 | }
33 | ]
34 | }
35 | ]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sublime Favorites
2 |
3 | A plugin for displaying Favorites (list of frequently used documents) in the [Sublime Text 3](http://sublimetext.com "Sublime Text") editor.
4 |
5 | While plugin functionality overlaps with some other similar ST3 plugins, it has a very strong distinction - it offers visual management of the Favorites' items.
6 |
7 | ## Installation
8 |
9 | Note the plugin was developed and tested against ST3 but not ST2.
10 |
11 | *__Package Control__*
12 |
13 | _Not available yet: waiting for Sublime team approval._
14 | You can install the pluging [Package Control](https://packagecontrol.io/packages/Favorites).
15 |
16 | *__Manual__*
17 |
18 | * Remove the package, if installed, using Package Control.
19 | * Add a repository: `https://github.com/oleg-shilo/sublime-favorites.git`
20 | * Install `sublime-favorites` with Package Control.
21 |
22 | You can also install the plugin by cloning `sublime-favorites` repository into your Packages folder or manually placing the download package there.
23 |
24 | ## Usage
25 | The plugin uses a dedicated view group on right side (favorites panel) to mimic a "side bar" containing the list of "favorite documents".
26 |
27 | All visual elements in the panel can be double-clicked to invoke the default command associated with the element. Alternatively user can hover the mouse cursor over the item to trigger an interactive tooltip, which allows invoking multiple commands associated with the visual element.
28 |
29 | To start working with Favorites just make the favorites panel visible (e.g. press `cmd+shift+p` and type/select `Favorites: Toggle Visibility`).
30 |
31 | Alternatively, you can configure custom binding instead:
32 |
33 | _Open keymap menu_
34 |
35 | Preferences > Key Bindings > Default (...).sublime-keymap - User
36 |
37 | _Add mapping:_
38 |
39 | ```
40 | { "keys": ["alt+f", "alt+f"], "command": "show_favorites" }
41 | ```
42 |
43 | 
44 |
45 | ## Functionality
46 |
47 | 1. *Toggle Visibility*
48 | Show/Hide favorites panel either with *Command Palette* or by the configured shortcut (e.g. [alt+f, alt+f]).
49 |
50 | 2. *Add active document to favorites*
51 | Double-click the `Add` command at the top of the panel.
52 | Alternatively, hover over `Add` command at the top of the panel and then click `Add active view...` on the tooltip.
53 |
54 | 3. Remove the item (document) from the favorites.
55 | Hover over the document item in the panel and then click `Remove from...` on the tooltip.
56 |
57 | 4. *Open the item (document)*
58 | Double-click the document item in the panel.
59 | Alternatively, hover the document item in the panel and then click `Open...` on the tooltip.
60 |
61 | 5. *Edit Favorites data file directly*
62 | Double-click the `Edit` command at the top of the panel.
63 | Alternatively, hover over `Edit` command at the top of the panel and then click `Edit...` on the tooltip.
64 |
65 | 6. *Project specific favorites*
66 | The plugin maintains a separate list of favorites per project. It is merged with the global favorites if the project file is loaded into ST. The project favorites are always placed in the bottom section of the favorites panel. All per-project items can be dealt with (e.g. Add, Remove, edit) the same ways as global ones.
67 |
68 | 7. *File aliases*
69 | By default the items in the favorites panel appears with their file name listed. However if a custom name is more beneficial a file alias can be assigned to the item in the data file via "Edit favorites" command.
70 |
71 | The format is simple: `|`:
72 | ```
73 | shelloverlay|Q:\Extras\Utils\TortoiseIconOverlays.cs
74 | ```
75 |
76 | 
77 |
78 |
79 | Practically all functionality available via favorites panel is also available via *Command Palette*:
80 | 
81 |
82 | ## Settings
83 |
84 | You can also configure plugin to:
85 | 1. Hide the group on closing the panel when it is the only view in the group.
86 | 2. Always place favorites panel in the individual most-right column. Only up to 4 columns layout is supported.is alse available
87 | 3. Use [Favorite Files](https://github.com/facelessuser/FavoriteFiles) plugin data file.
88 | The integration is limited to reading `Favorite Files` data file, flattening it and allowing to open files on double-click on the item in the Favorites panel.
89 |
90 | _favorites.sublime-settings_
91 |
92 | ```js
93 | {
94 | "close_empty_group_on_closing_panel": true,
95 | "show_in_new_group": true,
96 | "favorite_files_integration_enabled": false
97 | }
98 | ```
99 |
--------------------------------------------------------------------------------
/fav.sublime-syntax:
--------------------------------------------------------------------------------
1 | %YAML 1.2
2 | ---
3 | # See http://www.sublimetext.com/docs/3/syntax.html
4 | name: Fav
5 | file_extensions:
6 | - ec
7 | - fav
8 | scope: text.html.favorites
9 | contexts:
10 | main:
11 | - match: ([#]{1,6})(.*)+(:)(\d+)
12 | captures:
13 | 1: string.other.link.title.markdown
14 | 2: punctuation.definition.constant.markdown
15 | 3: entity.name.section
16 | 4: entity.name.section
17 |
18 | - match: '\b(Add|Edit|Refresh|Open all)\b'
19 | scope: keyword.control.example-c
--------------------------------------------------------------------------------
/favorites.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 | import codecs
4 | import os
5 | import shutil
6 | import sys
7 | from os import path
8 | from sublime import Region
9 | import socket
10 | import subprocess
11 | import errno
12 |
13 | # version = 1.0.8
14 |
15 | if sys.version_info < (3, 3):
16 | raise RuntimeError('Favorites works with Sublime Text 3 only.')
17 |
18 | # ============================================================
19 | # Packages/.sublime-package/favorites.py
20 | package_name = path.basename(path.dirname(__file__)).replace('.sublime-package', '')
21 |
22 | fav_syntax = 'Packages/'+package_name+'/fav.tmLanguage'
23 | plugin_name = 'favorites'
24 | panel_name = 'Favorites'
25 |
26 | def using_Favorite_Files_data():
27 | return sublime.load_settings(plugin_name+".sublime-settings").get('favorite_files_integration_enabled', True)
28 |
29 | # -----------------
30 | def favorites_data_path(per_project):
31 | file = None
32 |
33 | if per_project:
34 | project = sublime.active_window().project_file_name()
35 | if project:
36 | file = project + '.favorites'
37 | else:
38 | file = os.path.join(sublime.packages_path(), 'User', 'favorites.txt')
39 |
40 | if file and not path.exists(file):
41 | with open(file, "w") as f:
42 | f.write('')
43 |
44 | return file
45 | # -------------------------
46 | def show_integration_constrains_message():
47 | sublime.error_message('Since you are using "Favorite Files" plugin integration '+
48 | 'you have to use "Favorite Files" commands via command palette '+
49 | 'to add, remove or edit the file list.')
50 |
51 | # -------------------------
52 | def get_favorite_files_data():
53 | """
54 | Integration with Favorit_Files plugin
55 | It goes only as far as reading its data file, flattening it and allowing to
56 | open files on double-click on the item in the Favorites panel
57 | """
58 | import json
59 |
60 | file_name = os.path.join(sublime.packages_path(), 'User', 'favorite_files_list.json')
61 |
62 | with open(file_name) as data_file:
63 | data = json.load(data_file)
64 |
65 | result = []
66 | for f in data["files"]:
67 | result.append(f)
68 |
69 | for name in data["groups"].keys():
70 | for f in data["groups"][name]:
71 | result.append(f)
72 |
73 | return result
74 | # -------------------------
75 | def get_favorites(per_project):
76 | if using_Favorite_Files_data():
77 | return get_favorite_files_data()
78 | else:
79 | file = favorites_data_path(per_project)
80 | lines = []
81 | if file and os.path.exists(file):
82 | with codecs.open(file, "r", encoding='utf8') as f:
83 | content = f.read().strip()
84 | if content != '':
85 | lines = content.split('\n')
86 |
87 | return [x.strip() for x in lines]
88 | # -------------------------
89 | def set_favorites(lines, per_project):
90 | if using_Favorite_Files_data():
91 | show_integration_constrains_message()
92 | else:
93 | file = favorites_data_path(per_project)
94 | with codecs.open(file, "w", encoding='utf8') as f:
95 | f.write('\n'.join(lines))
96 | # -------------------------
97 | def del_favorites(lines, per_project):
98 | if not using_Favorite_Files_data():
99 | file = favorites_data_path(per_project)
100 | with codecs.open(file, "w", encoding='utf8') as f:
101 | f.write('\n'.join(lines))
102 | # -------------------------
103 | def get_favorite_path(index):
104 | # print(index)
105 | lines = get_favorites(False)
106 | p_lines = get_favorites(True)
107 |
108 | if index < len(lines):
109 | return extract_path(lines[index]);
110 |
111 | index -= len(lines)
112 | index -= items_offset # project favorites will have extra two lines in the header (items_offset)
113 | if index >= 0 and index < len(p_lines) :
114 | # print(index, '/',len(p_lines))
115 | return extract_path(p_lines[index]);
116 |
117 | return None
118 | # -------------------------
119 | def open_favorite_path(index):
120 | file = get_favorite_path(index)
121 | if file:
122 | focus_prev_view_group()
123 | open_path(file)
124 | # -------------------------
125 | def add_active_view(arg=None, per_project=False):
126 | if arg:
127 | file = arg
128 | else:
129 | file = sublime.active_window().active_view().file_name()
130 |
131 | lines = get_favorites(per_project)
132 | if not file in lines:
133 | lines.append(file)
134 | set_favorites(lines, per_project)
135 |
136 | refresh_favorites()
137 | # -------------------------
138 | def focus_prev_view_group():
139 | try:
140 | if favorites_listener.last_active_view:
141 | if favorites_listener.last_active_view == get_panel_view():
142 | group, _ = sublime.active_window().get_view_index(favorites_listener.last_active_view)
143 | else:
144 | group = 0
145 | sublime.active_window().focus_group(group)
146 | except:
147 | pass
148 | # -------------------------
149 | def remove_from_favorites(arg, per_project):
150 | file = arg
151 | lines = []
152 | for file in get_favorites(per_project):
153 | if file != arg:
154 | lines.append(file)
155 | set_favorites(lines, per_project)
156 | refresh_favorites()
157 | # -------------------------
158 | def remove_all_from_favorites(per_project):
159 | lines = []
160 | set_favorites(lines, per_project)
161 | refresh_favorites()
162 | # -------------------------
163 | def edit_favorites(per_project):
164 | if using_Favorite_Files_data():
165 | show_integration_constrains_message()
166 | else:
167 | focus_prev_view_group()
168 | open_path(favorites_data_path(per_project))
169 | # -------------------------
170 | def refresh_favorites():
171 | panel_view = get_panel_view()
172 | if panel_view:
173 | panel_view.run_command(plugin_name+'_generator')
174 | # -------------------------
175 | def open_all_favorites(per_project):
176 |
177 | for item in get_favorites(per_project):
178 | file = extract_path(item)
179 | view = sublime.active_window().find_open_file(file)
180 | if not view:
181 | view = sublime.active_window().open_file(file)
182 |
183 | if view:
184 | sublime.active_window().focus_view(view)
185 | # -------------------------
186 | def open_path(file):
187 | view = sublime.active_window().find_open_file(file)
188 | if not view:
189 | view = sublime.active_window().open_file(file)
190 | if view:
191 | sublime.active_window().focus_view(view)
192 | # -------------------------
193 | def extract_title(text):
194 | if text:
195 | parts = text.split('|')
196 | if len(parts) == 1:
197 | return path.basename(text.strip())
198 | else:
199 | return parts[0]
200 | return ''
201 | # -------------------------
202 | def extract_path(text):
203 | if text:
204 | parts = text.split('|')
205 | if len(parts) > 1:
206 | return parts[len(parts)-1].strip()
207 | else:
208 | return text
209 | # -------------------------
210 | tooltip_template = """
211 |
212 |
216 | %s
217 |
218 | """
219 | # -------------------------
220 | class show_favorites(sublime_plugin.TextCommand):
221 | def run(self, edit):
222 | show_panel.run(self, edit);
223 | # -------------------------
224 | # ======================================================
225 | class add_favorites(sublime_plugin.TextCommand):
226 | # -----------------
227 | def run(self, edit):
228 | add_favorites.do(self.view, False)
229 | # -----------------
230 | def do(view, per_project):
231 | file = view.file_name()
232 | if file:
233 | add_active_view(file, per_project)
234 | else:
235 | sublime.error_message('You can add to favorites only view that has been saved.')
236 | # -------------------------
237 | class add_proj_favorites(sublime_plugin.TextCommand):
238 | # -----------------
239 | def is_enabled(self):
240 | return self.view.window().project_file_name() != None
241 | # -----------------
242 | def run(self, edit):
243 | edit_favorites(True)
244 | # -------------------------
245 | class edit_favorites_file(sublime_plugin.TextCommand):
246 | # -----------------
247 | def run(self, edit):
248 | edit_favorites(False)
249 | # -------------------------
250 | class edit_proj_favorites_file(sublime_plugin.TextCommand):
251 | # -----------------
252 | def is_enabled(self):
253 | return self.view.window().project_file_name() != None
254 | # -----------------
255 | def run(self, edit):
256 | edit_favorites(True)
257 | # -------------------------
258 | class remove_favorites_file(sublime_plugin.TextCommand):
259 | # -----------------
260 | def run(self, edit):
261 | remove_all_from_favorites(False)
262 | # -------------------------
263 | class remove_proj_favorites_file(sublime_plugin.TextCommand):
264 | # -----------------
265 | def is_enabled(self):
266 | return self.view.window().project_file_name() != None
267 | # -----------------
268 | def run(self, edit):
269 | remove_all_from_favorites(True)
270 | # -------------------------
271 | class openall_favorites(sublime_plugin.TextCommand):
272 | # -----------------
273 | def run(self, edit):
274 | open_all_favorites(False)
275 | # -------------------------
276 | class openall_proj_favorites(sublime_plugin.TextCommand):
277 | # -----------------
278 | def is_enabled(self):
279 | return self.view.window().project_file_name() != None
280 | # -----------------
281 | def run(self, edit):
282 | open_all_favorites(True)
283 | # ======================================================
284 |
285 | # -------------------------
286 | items_offset = 2
287 | # -----------------
288 | class favorites_generator(sublime_plugin.TextCommand):
289 | def run(self, edit):
290 | panel_view = self.view
291 |
292 | lines = get_favorites(False)
293 |
294 | map = "Add Edit Open all"
295 | map += "\n-----------------------"
296 | for line in lines:
297 | map += "\n"+extract_title(line)
298 |
299 | project = sublime.active_window().project_file_name()
300 | if project:
301 | map += '\n\n--- "'+path.basename(project).replace('.sublime-project', '" project')+' ---'
302 | p_lines = get_favorites(True)
303 | for line in p_lines:
304 | map += '\n' + extract_title(line)
305 |
306 | map_syntax = fav_syntax
307 |
308 | panel_view.set_read_only(False)
309 |
310 | all_text = sublime.Region(0, panel_view.size())
311 | panel_view.replace(edit, all_text, map)
312 | panel_view.set_scratch(True)
313 |
314 | panel_view.assign_syntax(map_syntax)
315 | panel_view.set_read_only(True)
316 | # -----------------
317 | class favorites_listener(sublime_plugin.EventListener):
318 | # -----------------
319 | last_active_view = None
320 | # -----------------
321 | def on_activated(self, view):
322 | if view != get_panel_view() and view.file_name():
323 | favorites_listener.last_active_view = view
324 | # -----------------
325 | def on_hover(self, view, point, hover_zone):
326 | if view.file_name() == panel_file():
327 | row, col = view.rowcol(point)
328 | if row == 0:
329 |
330 | project = sublime.active_window().project_file_name()
331 |
332 | callback = None
333 | html = ""
334 | command = view.substr(view.word(point)).lower()
335 | if command == "add":
336 | def add(arg):
337 | view.hide_popup()
338 | per_project = (arg == 'add_to_proj')
339 | add_active_view(None, per_project)
340 |
341 | file = sublime.active_window().active_view().file_name()
342 | link_open = ''
343 | if project:
344 | # link_open = file+'
'
345 | link_open += 'Add active view ('+os.path.basename(file)+')
'
346 | link_open += ' to favorites
'
347 | link_open += ' to "'+os.path.basename(project).replace('.sublime-project', '')+'" project favorites'
348 | else:
349 | link_open += 'Add active view ('+os.path.basename(file)+') to favorites'
350 |
351 |
352 | html = tooltip_template % (link_open)
353 | callback = add
354 |
355 | elif command == "edit":
356 | def refresh(arg):
357 | view.hide_popup()
358 | per_project = (arg == 'edit.proj')
359 | edit_favorites(per_project)
360 |
361 | html_content = 'Edit favorites file'
362 | if project:
363 | html_content += '
Edit "'+os.path.basename(project).replace('.sublime-project', '')+'" project favorites file'
364 |
365 | html = tooltip_template % (html_content)
366 |
367 | callback = refresh
368 |
369 | elif command == "Open" or "all" :
370 | def open(arg):
371 | view.hide_popup()
372 | per_project = (arg == 'proj')
373 | open_all_favorites(per_project)
374 |
375 | html_content = 'Open all favorites files'
376 | if project:
377 | html_content += '
Open all "'+os.path.basename(project).replace('.sublime-project', '')+'" project favorites files'
378 |
379 | html = tooltip_template % (html_content)
380 |
381 | callback = open
382 |
383 | elif command == "refresh":
384 | def refresh(arg):
385 | view.hide_popup()
386 | refresh_favorites()
387 | html = tooltip_template % ('Refresh favorites')
388 | callback = refresh
389 |
390 | else:
391 | return
392 |
393 | view.show_popup(html, location=point, flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY, max_width=600, on_navigate=callback)
394 |
395 | else:
396 | index = row-items_offset
397 | global_list = get_favorites(False)
398 | per_project = (index >= len(global_list))
399 |
400 | file = get_favorite_path(index)
401 |
402 | if file:
403 | link_open = file+'
'
404 | link_open += ' Open in active window
'
405 | link_open += ' Remove from the'
406 | if per_project:
407 | link_open += " project's favorites"
408 | else:
409 | link_open += ' favorites'
410 |
411 | html = tooltip_template % (link_open)
412 |
413 | def open(arg):
414 | view.hide_popup()
415 | if arg.startswith('remove.'):
416 | remove_from_favorites(file, per_project)
417 | else:
418 | open_path(arg)
419 |
420 | view.show_popup(html, location=point, flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY, max_width=600, on_navigate=open)
421 | # -----------------
422 | def on_post_text_command(self, view, command_name, args):
423 | # process double-click on code panel view`
424 | per_project = sublime.active_window().project_file_name()!= None
425 | if view.file_name() == panel_file():
426 | if command_name == 'drag_select' and 'by' in args.keys() and args['by'] == 'words':
427 | point = view.sel()[0].begin()
428 | row, col = view.rowcol(point)
429 | view.sel().clear()
430 |
431 | if row > 1:
432 | open_favorite_path(row - items_offset)
433 |
434 | elif row == 0:
435 | command = view.substr(view.word(point)).lower()
436 | if command == 'add':
437 | last_view = favorites_listener.last_active_view
438 | if last_view != view:
439 | add_active_view(last_view.file_name())
440 |
441 | elif command == 'edit':
442 | edit_favorites(per_project)
443 | elif command == 'refresh':
444 | refresh_favorites()
445 |
446 |
447 | #########################################################################################################################
448 | #
449 | # ============================================================
450 | # Layout management
451 | # ============================================================
452 | def settings():
453 | return sublime.load_settings(plugin_name+".sublime-settings")
454 | # -----------------
455 | def panel_file():
456 |
457 | plugin_dir = ''
458 |
459 | if hasattr(sublime, 'cache_path'):
460 | plugin_dir = sublime.cache_path()
461 | else:
462 | plugin_dir = 'cache'
463 | plugin_dir = os.path.join(os.getcwd(), plugin_dir)
464 |
465 | data_dir = path.join(plugin_dir, panel_name)
466 | if not path.exists(data_dir):
467 | os.makedirs(data_dir)
468 | return path.join(data_dir, panel_name)
469 | # -----------------
470 | def set_layout_columns(count, coll_width=0.75):
471 |
472 | if count == 1:
473 | sublime.active_window().run_command("set_layout", {"cells": [[0, 0, 1, 1]], "cols": [0.0, 1.0], "rows": [0.0, 1.0]})
474 |
475 | elif count == 2:
476 | sublime.active_window().run_command("set_layout", {"cells": [[0, 0, 1, 1], [1, 0, 2, 1]], "cols": [0.0, coll_width, 1.0], "rows": [0.0, 1.0]})
477 |
478 | elif count == 3:
479 | sublime.active_window().run_command("set_layout", {"cells": [[0, 0, 1, 1], [1, 0, 2, 1], [2, 0, 3, 1]], "cols": [0.0, 0.33, 0.66, 1.0], "rows": [0.0, 1.0]})
480 |
481 | elif count == 4:
482 | sublime.active_window().run_command("set_layout", {"cells": [[0, 0, 1, 1], [1, 0, 2, 1], [2, 0, 3, 1], [3, 0, 4, 1]], "cols": [0.0, 0.25, 0.5, 0.75, 1.0], "rows": [0.0, 1.0]})
483 | # -----------------
484 | def centre_line_of(view, region):
485 | (first_row,c) = view.rowcol(region.begin())
486 | (last_row,c) = view.rowcol(region.end())
487 | return int(first_row + (last_row - first_row)/2)
488 | # -----------------
489 | def get_panel_view():
490 | for v in sublime.active_window().views():
491 | if v.file_name() == panel_file():
492 | return v
493 | # -----------------
494 | def refresh_panel_for(view):
495 | panel_view = get_panel_view()
496 | if panel_view:
497 | panel_view.run_command(plugin_name+'_generator')
498 |
499 | # ===============================================================================
500 | class event_listener(sublime_plugin.EventListener):
501 | panel_closed_group = -1
502 | pre_close_active = None
503 | can_close = False
504 | # -----------------
505 | def on_load(self, view):
506 | if view.file_name() != panel_file():
507 | refresh_panel_for(view)
508 | # -----------------
509 | def on_pre_close(self, view):
510 | if view.file_name() == panel_file():
511 | event_listener.panel_closed_group, x = sublime.active_window().get_view_index(view)
512 | if len(sublime.active_window().views_in_group(event_listener.panel_closed_group)) == 1:
513 | event_listener.can_close = True
514 | # -----------------
515 | def on_close(self, view):
516 |
517 | def close_panel_group():
518 | """Removes the panel group, and scales up the rest of the layout"""
519 | layout = window.get_layout()
520 | cols = layout['cols']
521 | cells = layout['cells']
522 | last_col = len(cols) - 1
523 | panel_width = cols[len(cols) - 2]
524 |
525 | for i, col in enumerate(cols):
526 | if col > 0:
527 | cols[i] = col/panel_width
528 |
529 | del cols[last_col]
530 | del cells[len(cells) - 1]
531 | window.run_command("set_layout", layout)
532 |
533 | def focus_source_code():
534 | if event_listener.pre_close_active:
535 | window.focus_group(event_listener.pre_close_active[0])
536 | window.focus_view(event_listener.pre_close_active[1])
537 |
538 | enabled = settings().get('close_empty_group_on_closing_panel', True)
539 |
540 | if event_listener.can_close and enabled and view.file_name() == panel_file() and event_listener.panel_closed_group != -1:
541 | window = sublime.active_window()
542 | event_listener.can_close = False
543 | close_panel_group()
544 | sublime.set_timeout(focus_source_code, 100)
545 |
546 | event_listener.panel_closed_group = -1
547 | # -----------------
548 | def on_post_save_async(self, view):
549 | refresh_panel_for(view)
550 | # -----------------
551 | def on_activated_async(self, view):
552 | refresh_panel_for(view)
553 | # ===============================================================================
554 | class scroll_to_left(sublime_plugin.TextCommand):
555 | # -----------------
556 | def panel_view(next_focus_view=None):
557 |
558 | def do():
559 | get_panel_view().run_command('scroll_to_left')
560 |
561 | sublime.set_timeout(do, 100)
562 | # -----------------
563 | def run(self, edit):
564 | region = self.view.visible_region()
565 | y = self.view.text_to_layout(region.begin())[1]
566 | self.view.set_viewport_position((0, y), False)
567 |
568 | # ===============================================================================
569 | class show_panel:
570 | # -----------------
571 | def run(self, edit):
572 |
573 | def create_panel_group():
574 | """Adds a column on the right, and scales down the rest of the layout"""
575 | layout = self.view.window().get_layout()
576 | cols = layout['cols']
577 | cells = layout['cells']
578 | last_col = len(cols) - 1
579 | last_row = len(layout['rows']) - 1
580 | width = 1 - settings().get("panel_width", 0.17)
581 |
582 | for i, col in enumerate(cols):
583 | if col > 0:
584 | cols[i] = col*width
585 |
586 | cols.append(1)
587 | newcell = [last_col, 0, last_col + 1, last_row]
588 | cells.append(newcell)
589 | window.run_command("set_layout", layout)
590 | groups = window.num_groups()
591 | return (groups + 1)
592 |
593 | window = self.view.window()
594 | groups = window.num_groups()
595 | current_group = window.active_group()
596 | current_view = self.view
597 |
598 | panel_view = get_panel_view()
599 |
600 | if not panel_view:
601 | panel_group = 1
602 |
603 | show_in_new_group = settings().get("show_in_new_group", True)
604 |
605 | if not show_in_new_group:
606 | if groups == 1:
607 | set_layout_columns(2)
608 | groups = window.num_groups()
609 |
610 | else:
611 | panel_group = create_panel_group()
612 |
613 | with open(panel_file(), "w") as file:
614 | file.write('')
615 |
616 | panel_view = window.open_file(panel_file())
617 | panel_view.settings().set("word_wrap", False)
618 | window.set_view_index(panel_view, panel_group, 0)
619 | panel_view.sel().clear()
620 |
621 | panel_view.settings().set("gutter", False)
622 |
623 | def focus_source_code():
624 | window.focus_group(current_group)
625 | window.focus_view(current_view)
626 |
627 | sublime.set_timeout_async(focus_source_code, 100)
628 |
629 | else:
630 | # close group only if panel is the only file in it
631 | panel_group = window.get_view_index(panel_view)[0]
632 | if len(window.views_in_group(panel_group)) == 1:
633 | event_listener.pre_close_active = [current_group, current_view]
634 | event_listener.can_close = True
635 | window.focus_view(panel_view)
636 | window.run_command("close_file")
637 | # ===============================================================================
638 |
--------------------------------------------------------------------------------
/favorites.sublime-settings:
--------------------------------------------------------------------------------
1 | {
2 | "close_empty_group_on_closing_panel": true,
3 | "favorite_files_integration_enabled": false,
4 | "show_in_new_group": true
5 | }
6 |
--------------------------------------------------------------------------------
/images/commands.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oleg-shilo/sublime-favorites/517974836c538fa1d03e5aa5432aaddeb3c7f989/images/commands.png
--------------------------------------------------------------------------------
/images/favorites.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oleg-shilo/sublime-favorites/517974836c538fa1d03e5aa5432aaddeb3c7f989/images/favorites.gif
--------------------------------------------------------------------------------
/images/global_vs_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oleg-shilo/sublime-favorites/517974836c538fa1d03e5aa5432aaddeb3c7f989/images/global_vs_project.png
--------------------------------------------------------------------------------
/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "install": "messages/install.txt",
3 | "1.0.1": "messages/1.0.1.txt",
4 | "1.0.2": "messages/1.0.2.txt",
5 | "1.0.3": "messages/1.0.3.txt",
6 | "1.0.4": "messages/1.0.4.txt"
7 | "1.0.5": "messages/1.0.5.txt"
8 | }
9 |
--------------------------------------------------------------------------------
/messages/1.0.1.txt:
--------------------------------------------------------------------------------
1 | Features:
2 |
3 | 1. Added integration with `Favorite Files` plugin.
4 | The integration is limited to using `Favorite Files` data file, flattening it and allowing to open files on double-click on the item in the Favorites panel.
5 |
6 | In order to enable `Favorite Files` integration set `favorite_files_integration_enabled` setting to true:
7 | ```js
8 | {
9 | "favorite_files_integration_enabled": true
10 | }
11 | ```
12 |
13 |
--------------------------------------------------------------------------------
/messages/1.0.2.txt:
--------------------------------------------------------------------------------
1 | Features:
2 |
3 | 1. Fixed Issue #1: Crash; nothing showing up in Favorites panel
4 |
--------------------------------------------------------------------------------
/messages/1.0.3.txt:
--------------------------------------------------------------------------------
1 | Features/Changes:
2 |
3 | 1. Added commands for all major operations
4 | 2. Issues #2: Allow favorites.txt file to be created per-project, at project root
5 | 3. Issues #3: Allow favorites.yml as alternative to favorites.txt
6 | By default the items in the favorites panel appears with their file name listed. However if a custom name is more beneficial a file alias can be assigned to the item in the data file via "Edit favorites" command.
7 |
8 | The format is simple: |:
9 | ```
10 | shelloverlay|Q:\Extras\Utils\TortoiseIconOverlays.cs
11 | ```
12 | 4. Issues #4: Allow opening all favorites with a single command
13 |
--------------------------------------------------------------------------------
/messages/1.0.4.txt:
--------------------------------------------------------------------------------
1 | Features/Changes:
2 |
3 | 1. Fixed problem with opening favorite items in absence of a loaded project/folder.
--------------------------------------------------------------------------------
/messages/1.0.5.txt:
--------------------------------------------------------------------------------
1 | Features/Changes:
2 |
3 | 1. Feature request #6: Added 'remove all' command
--------------------------------------------------------------------------------
/messages/1.0.7.txt:
--------------------------------------------------------------------------------
1 | Features/Changes:
2 |
3 | 1. Removed default key binding as it conflicts with default `alt+f` OS handling.
4 | Users should configure custom binding instead:
5 | _Open keymap menu_
6 | Preferences > Key Bindings > Default (...).sublime-keymap - User
7 | _Add mapping:_
8 | ```
9 | { "keys": ["alt+f", "alt+f"], "command": "show_favorites" }
10 | ```
--------------------------------------------------------------------------------
/messages/install.txt:
--------------------------------------------------------------------------------
1 | Welcome to Favorites!
2 |
3 | For more information see the README.md at https://github.com/oleg-shilo/sublime-favorites
4 | ---------------------------------------------------------------------------------------
5 | A plugin for displaying Favorites (list of frequently used documents) in the Sublime Text 3 editor.
6 |
7 | While plugin functionality overlaps with some other similar ST3 plugins, it has vary strong distinction - it offers visual management of the Favorites' items.
8 |
9 | Usage
10 | The plugin uses a dedicated view group Favorites (on right side) to mimic a "side bar" with the content (code tree).
11 |
12 | * Toggle Visibility
13 | Show/Hide favorites panel either with Command Palette or by the configured shortcut (e.g. [alt+f, alt+f]).
14 |
15 | * Add active document to favorites
16 | Double-click the Add command at the top of the panel.
17 |
18 | * Remove the item (document) from the favorites.
19 | Hover over the document item in the panel and then click Remove from... on the tooltip.
20 |
21 | * Open the item (document)
22 | Double-click the document item in the panel.
23 |
24 | *Edit Favorites data file directly
25 | Double-click the Edit command at the top of the panel.
26 |
--------------------------------------------------------------------------------