Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 337 lines (277 sloc) 9.762 kb
0082fd9 @titoBouzout Mayor rewrite
authored
1 import sublime, sublime_plugin
2 from os.path import exists, normpath
3 from hashlib import sha1
4
5 try:
6 from cPickle import load, dump
7 except:
8 sublime.error_messsage('BufferScroll: Unable to load module cPickle.')
9
10 debug = False
11
12 # open
13
14 database = sublime.packages_path()+'/User/BufferScroll.bin'
15 if exists(database):
16 try:
17 db = load(file(database, 'rb'));
18 except:
19 db = {}
20 else:
21 db = {}
22
23 # upgrade
24 from os import remove, rename
25 try:
26 remove(sublime.packages_path()+'/User/BufferScroll.sublime-settings')
27 except:
28 pass
29 try:
30 rename(sublime.packages_path()+'/User/BufferScrollUser.sublime-settings',
31 sublime.packages_path()+'/User/BufferScroll.sublime-settings')
32 except:
33 pass
34
35 # settings
36
37 s = sublime.load_settings('BufferScroll.sublime-settings')
38 class Pref():
8879501 @titoBouzout Add options to save syntax and color scheme
authored
39 def load(self):
0082fd9 @titoBouzout Mayor rewrite
authored
40 Pref.remember_color_scheme = s.get('remember_color_scheme', False)
38c5639 @titoBouzout Allow to keep in synch bookmarks, marks and folds.
authored
41 Pref.synch_bookmarks = s.get('synch_bookmarks', False)
42 Pref.synch_marks = s.get('synch_marks', False)
43 Pref.synch_folds = s.get('synch_folds', False)
0082fd9 @titoBouzout Mayor rewrite
authored
44 Pref.current_view = -1
45 version = 6
46 version_current = s.get('version')
47 if version_current != version:
48 s.set('version', version)
49 db = {}
50 sublime.save_settings('BufferScroll.sublime-settings')
8879501 @titoBouzout Add options to save syntax and color scheme
authored
51
52 Pref().load()
38c5639 @titoBouzout Allow to keep in synch bookmarks, marks and folds.
authored
53 s.add_on_change('remember_color_scheme', lambda:Pref().load())
54 s.add_on_change('synch_bookmarks', lambda:Pref().load())
55 s.add_on_change('synch_marks', lambda:Pref().load())
56 s.add_on_change('synch_folds', lambda:Pref().load())
8879501 @titoBouzout Add options to save syntax and color scheme
authored
57
dbba202 @titoBouzout Public
authored
58 class BufferScroll(sublime_plugin.EventListener):
59
64a2f1f @titoBouzout Restore scroll for when a file is modified by an external application
authored
60 # restore on load for new opened tabs or previews.
dbba202 @titoBouzout Public
authored
61 def on_load(self, view):
0082fd9 @titoBouzout Mayor rewrite
authored
62 self.restore(view, 'on_load')
3a68cd7 @titoBouzout Try restore clon views.
authored
63
cdd395f @titoBouzout Fix selection is cleared without adding a selection
authored
64 # restore on load for cloned views
bdc5510 @titoBouzout Use on_clone
authored
65 def on_clone(self, view):
0082fd9 @titoBouzout Mayor rewrite
authored
66 self.restore(view, 'on_clone')
dbba202 @titoBouzout Public
authored
67
8ddda67 @titoBouzout Save marks, some clean-ups
authored
68 # the application is not sending "on_close" event when closing
69 # or switching the projects, then we need to save the data on focus lost
fa595ac @titoBouzout Workaround for: no dispath of on_close event when switching project o…
authored
70 def on_deactivated(self, view):
0082fd9 @titoBouzout Mayor rewrite
authored
71 self.save(view, 'on_deactivated')
38c5639 @titoBouzout Allow to keep in synch bookmarks, marks and folds.
authored
72 self.synch(view)
0082fd9 @titoBouzout Mayor rewrite
authored
73
74 # track the current_view. See next event listener
75 def on_activated(self, view):
76 if view.file_name() and not view.settings().get('is_widget'):
77 Pref.current_view = view.id() # this id is not unique
fa595ac @titoBouzout Workaround for: no dispath of on_close event when switching project o…
authored
78
6d12104 @titoBouzout Save data as int
authored
79 # save the data when background tabs are closed
80 # these that don't receive "on_deactivated"
8ddda67 @titoBouzout Save marks, some clean-ups
authored
81 def on_close(self, view):
0082fd9 @titoBouzout Mayor rewrite
authored
82 # current_view will receive event on_deactivated ( when closing )
83 # which provides more data than on_close
84 # for example a "get_view_index" ..
85 if Pref.current_view != view.id():
86 self.save(view, 'on_close')
8ddda67 @titoBouzout Save marks, some clean-ups
authored
87
6d12104 @titoBouzout Save data as int
authored
88 # save data for focused tab when saving
0082fd9 @titoBouzout Mayor rewrite
authored
89 def on_post_save(self, view):
90 self.save(view, 'on_post_save')
656030e @titoBouzout Store data when saving buffer
authored
91
0082fd9 @titoBouzout Mayor rewrite
authored
92 # saving
6b8ac2e @titoBouzout Fix where parameter for when a view is loading
authored
93 def save(self, view, where = 'unknow'):
0082fd9 @titoBouzout Mayor rewrite
authored
94 if not view.file_name() or view.settings().get('is_widget'):
95 return
96
97 id, index = self.view_id(view)
98
99 if debug:
100 print '-----------------------------------'
101 print 'saving from '+where
102 print view.file_name()
103 print 'id '+id
104 print 'position in tabbar '+index
f79ae6a @titoBouzout User new api view.folded_regions
authored
105
0082fd9 @titoBouzout Mayor rewrite
authored
106
107 # creates an object for this view, if it is unknow to the package
108 if id not in db:
109 db[id] = {}
110 if 'l' not in db[id]:
111 db[id]['l'] = {}
112
113 # if the result of the new collected data is different
114 # from the old data, then will write to disk
115 old_db = dict(db[id])
6d12104 @titoBouzout Save data as int
authored
116
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
117 # if the size of the view change outside the application skip restoration
118 # if not we will restore folds in funny positions, etc...
0082fd9 @titoBouzout Mayor rewrite
authored
119 db[id]['id'] = long(view.size())
120
121 # scroll
122 if int(sublime.version()) >= 2151:
123 # save the scroll with "index" as the id ( usefull for cloned views )
124 db[id]['l'][index] = view.viewport_position()
125 # also save as default if no exists
126 if '0' not in db[id]['l']:
127 db[id]['l']['0'] = view.viewport_position()
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
128
a434969 @titoBouzout Improves scroll restoration
authored
129 # selections
0082fd9 @titoBouzout Mayor rewrite
authored
130 db[id]['s'] = [[item.a, item.b] for item in view.sel()]
131
132 # # marks
133 db[id]['m'] = [[item.a, item.b] for item in view.get_regions("mark")]
134
135 # # bookmarks
136 db[id]['b'] = [[item.a, item.b] for item in view.get_regions("bookmarks")]
f79ae6a @titoBouzout User new api view.folded_regions
authored
137
1dc9cbc @titoBouzout New: ability to refold
authored
138 # previous folding save, to be able to refold
139 if 'f' in db[id] and list(db[id]['f']) != []:
140 db[id]['pf'] = list(db[id]['f'])
141
a434969 @titoBouzout Improves scroll restoration
authored
142 # folding
a4f915d @titoBouzout At the end sublime.version() is an string.
authored
143 if int(sublime.version()) >= 2167:
0082fd9 @titoBouzout Mayor rewrite
authored
144 db[id]['f'] = [[item.a, item.b] for item in view.folded_regions()]
7be5ced @titoBouzout Take care of old sublime versions
authored
145 else:
146 folds = view.unfold(sublime.Region(0, view.size()))
0082fd9 @titoBouzout Mayor rewrite
authored
147 db[id]['f'] = [[item.a, item.b] for item in folds]
7be5ced @titoBouzout Take care of old sublime versions
authored
148 view.fold(folds)
8ddda67 @titoBouzout Save marks, some clean-ups
authored
149
8879501 @titoBouzout Add options to save syntax and color scheme
authored
150 # color_scheme http://www.sublimetext.com/forum/viewtopic.php?p=25624#p25624
151 if Pref.remember_color_scheme:
0082fd9 @titoBouzout Mayor rewrite
authored
152 db[id]['c'] = view.settings().get('color_scheme')
8879501 @titoBouzout Add options to save syntax and color scheme
authored
153
154 # syntax
0082fd9 @titoBouzout Mayor rewrite
authored
155 db[id]['x'] = view.settings().get('syntax')
156
157 # write to disk only if something changed
158 if old_db != db[id]:
159 if debug:
160 print id
161 print db[id];
162 sublime.set_timeout(lambda:self.write(), 0)
163
164 def view_id(self, view):
165 if not view.settings().has('buffer_scroll_name'):
166 view.settings().set('buffer_scroll_name', sha1(normpath(view.file_name().encode('utf-8'))).hexdigest()[:8])
167 return (view.settings().get('buffer_scroll_name'), self.view_index(view))
168
169 def view_index(self, view):
170 window = view.window();
171 if not window:
172 window = sublime.active_window()
173 index = window.get_view_index(view)
174 if index and index != (0,0) and index != (0,-1) and index != (-1,-1):
175 return str(index)
176 else:
177 return '0'
178
179 def write(self):
180 if debug:
181 print 'writting to disk'
182 dump(db, file(database, "wb"))
183
6b8ac2e @titoBouzout Fix where parameter for when a view is loading
authored
184 def restore(self, view, where = 'unknow'):
0082fd9 @titoBouzout Mayor rewrite
authored
185 if not view.file_name() or view.settings().get('is_widget'):
186 return
187
6868451 @titoBouzout Something forget to upload
authored
188 if view.is_loading():
6b8ac2e @titoBouzout Fix where parameter for when a view is loading
authored
189 sublime.set_timeout(lambda: self.restore(view, where), 100)
0082fd9 @titoBouzout Mayor rewrite
authored
190 else:
3a68cd7 @titoBouzout Try restore clon views.
authored
191
0082fd9 @titoBouzout Mayor rewrite
authored
192 id, index = self.view_id(view)
64a2f1f @titoBouzout Restore scroll for when a file is modified by an external application
authored
193
0082fd9 @titoBouzout Mayor rewrite
authored
194 if debug:
195 print '-----------------------------------'
196 print 'restoring from '+where
197 print view.file_name()
198 print 'id '+id
199 print 'position in tabbar '+index
f520ef5 @titoBouzout Small tweaks
authored
200
0082fd9 @titoBouzout Mayor rewrite
authored
201 if id in db:
cb23530 @titoBouzout Improves restoring when view is moved of index
authored
202
0082fd9 @titoBouzout Mayor rewrite
authored
203 # if the view changed outside of the application, don't restore folds etc
204 if db[id]['id'] == long(view.size()):
3a68cd7 @titoBouzout Try restore clon views.
authored
205
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
206 # fold
207 rs = []
0082fd9 @titoBouzout Mayor rewrite
authored
208 for r in db[id]['f']:
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
209 rs.append(sublime.Region(int(r[0]), int(r[1])))
210 if len(rs):
211 view.fold(rs)
212
213 # selection
0082fd9 @titoBouzout Mayor rewrite
authored
214 if len(db[id]['s']) > 0:
cdd395f @titoBouzout Fix selection is cleared without adding a selection
authored
215 view.sel().clear()
0082fd9 @titoBouzout Mayor rewrite
authored
216 for r in db[id]['s']:
217 view.sel().add(sublime.Region(int(r[0]), int(r[1])))
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
218
219 # marks
220 rs = []
0082fd9 @titoBouzout Mayor rewrite
authored
221 for r in db[id]['m']:
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
222 rs.append(sublime.Region(int(r[0]), int(r[1])))
223 if len(rs):
224 view.add_regions("mark", rs, "mark", "dot", sublime.HIDDEN | sublime.PERSISTENT)
225
226 # bookmarks
227 rs = []
0082fd9 @titoBouzout Mayor rewrite
authored
228 for r in db[id]['b']:
40a3812 @titoBouzout If the view changes outside the application skip restoration.
authored
229 rs.append(sublime.Region(int(r[0]), int(r[1])))
230 if len(rs):
231 view.add_regions("bookmarks", rs, "bookmarks", "bookmark", sublime.HIDDEN | sublime.PERSISTENT)
3a68cd7 @titoBouzout Try restore clon views.
authored
232
0082fd9 @titoBouzout Mayor rewrite
authored
233 # color scheme
234 if Pref.remember_color_scheme and 'c' in db[id] and view.settings().get('color_scheme') != db[id]['c']:
235 view.settings().set('color_scheme', db[id]['c'])
8879501 @titoBouzout Add options to save syntax and color scheme
authored
236
0082fd9 @titoBouzout Mayor rewrite
authored
237 # syntax
238 if view.settings().get('syntax') != db[id]['x']:
239 view.settings().set('syntax', db[id]['x'])
8879501 @titoBouzout Add options to save syntax and color scheme
authored
240
6868451 @titoBouzout Something forget to upload
authored
241 # scroll
0082fd9 @titoBouzout Mayor rewrite
authored
242 if int(sublime.version()) >= 2151:
243 if index in db[id]['l']:
244 view.set_viewport_position(tuple(db[id]['l'][index]), False)
245 else:
246 view.set_viewport_position(tuple(db[id]['l']['0']), False)
8879501 @titoBouzout Add options to save syntax and color scheme
authored
247
38c5639 @titoBouzout Allow to keep in synch bookmarks, marks and folds.
authored
248 def synch(self, view):
249 if not view.file_name() or view.settings().get('is_widget'):
250 return
251
252 # if there is something to synch
253 if not Pref.synch_bookmarks and not Pref.synch_marks and not Pref.synch_folds:
254 return
255
256 # if there is clones
257 clones = []
258 for window in sublime.windows():
259 for _view in window.views():
260 if _view.file_name() == view.file_name() and view.id() != _view.id():
261 clones.append(_view)
262 if not clones:
263 return
264
265 id, index = self.view_id(view)
266
267 if Pref.synch_bookmarks:
268 bookmarks = []
269 for r in db[id]['b']:
270 bookmarks.append(sublime.Region(int(r[0]), int(r[1])))
271
272 if Pref.synch_marks:
273 marks = []
274 for r in db[id]['m']:
275 marks.append(sublime.Region(int(r[0]), int(r[1])))
276
277 if Pref.synch_folds:
278 folds = []
279 for r in db[id]['f']:
280 folds.append(sublime.Region(int(r[0]), int(r[1])))
281
282 for _view in clones:
283
284 # bookmarks
285 if Pref.synch_bookmarks and bookmarks:
286 if bookmarks != _view.get_regions('bookmarks'):
287 if debug:
288 print 'synching bookmarks'
289 _view.add_regions("bookmarks", bookmarks, "bookmarks", "bookmark", sublime.HIDDEN | sublime.PERSISTENT)
290 else:
291 if debug:
292 print 'skipping synch of bookmarks these are equal'
293
294 # marks
295 if Pref.synch_marks and marks:
296 if marks != _view.get_regions('mark'):
297 if debug:
298 print 'synching marks'
299 _view.add_regions("mark", marks, "mark", "dot", sublime.HIDDEN | sublime.PERSISTENT)
300 else:
301 if debug:
302 print 'skipping synch of marks these are equal'
303
304 # folds
305 if Pref.synch_folds and folds:
306 if int(sublime.version()) >= 2167:
307 if folds != _view.folded_regions():
308 if debug:
309 print 'synching folds'
310 _view.unfold(sublime.Region(0, _view.size()))
311 _view.fold(folds)
312 else:
313 if debug:
314 print 'skipping synch of folds these are equal'
315 else:
316 if debug:
317 print 'synching folds'
318 _view.unfold(sublime.Region(0, _view.size()))
319 _view.fold(folds)
320
1dc9cbc @titoBouzout New: ability to refold
authored
321 class BufferScrollForget(sublime_plugin.ApplicationCommand):
8879501 @titoBouzout Add options to save syntax and color scheme
authored
322 def run(self, what):
323 if what == 'color_scheme':
1dc9cbc @titoBouzout New: ability to refold
authored
324 sublime.active_window().active_view().settings().erase('color_scheme')
325
326 class BufferScrollReFold(sublime_plugin.WindowCommand):
327 def run(self):
328 view = sublime.active_window().active_view()
329 if view:
330 id, index = BufferScroll().view_id(view)
331 if id in db:
332 if 'pf' in db[id]:
333 rs = []
334 for r in db[id]['pf']:
335 rs.append(sublime.Region(int(r[0]), int(r[1])))
336 if len(rs):
337 view.fold(rs)
Something went wrong with that request. Please try again.