public
Created

Sublime Plugin to Save Auto Save Untitled Tabs

  • Download Gist
saveUntitledFile.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
import sublime, sublime_plugin
import time, os
 
# This class executes a callback function once self.delay seconds have elapsed since the last call to timer.notify()
# This allows a method like on_modified to repeatedly call notify without triggering the event multiple times per second.
class DelayedTimer:
def __init__(self, delay, callback):
self.delay = delay
self.callback = callback
self.lastRequest = 0
 
self.scheduleTimer()
 
def scheduleTimer(self):
sublime.set_timeout(self.onTimer, 100)
 
def onTimer(self):
self.scheduleTimer()
if self.lastRequest > 0 and self.lastRequest + self.delay < time.time():
self.lastRequest = 0
self.callback()
 
def notify(self):
self.lastRequest = time.time()
 
class SaveUntitledFiles(sublime_plugin.EventListener):
def __init__(self):
self.timer = DelayedTimer(5, self.saveViews)
 
# self.views will be a mapping of buffer id to view object or None
# if the value is None then it does not need to be saved, it is just storing the buffer id so we know we have it
# if the value is a view object, then it needs to be saved
self.views = {}
 
self.path = os.path.join(sublime.packages_path(), 'User', 'UntitledFiles')
if not os.path.exists(self.path):
os.makedirs(self.path)
 
# It appears that reading and saving the files in the constructor does not always work.
# A small delay seems to allow everything to finish
self.enabled = False
sublime.set_timeout(self.enable, 100)
 
def enable(self):
self.enabled = True
self.reopenFiles()
 
# Timer Callback
def saveViews(self):
self.removeOldFiles()
 
for id in self.views:
self.saveView(self.views[id])
 
def saveView(self, view):
# No changes since last timer fire
if view == None:
return
 
# read the contents of the view and save it
name = 'buffer_'+str(view.buffer_id())
content = view.substr(sublime.Region(0, view.size()))
with open(os.path.join(self.path, name), 'wb') as f:
f.write(content)
 
# mark the view as not requiring another save
self.views[view.buffer_id()] = None
 
# remove any of the saved buffers that have since been closed
def removeOldFiles(self):
files = os.listdir(self.path)
for filename in files:
id = int(filename.split('buffer_')[1])
if id not in self.views:
os.remove(os.path.join(self.path, filename))
 
def reopenFiles(self):
files = os.listdir(self.path)
for filename in files:
with open(os.path.join(self.path, filename), 'rb') as f:
content = f.read()
os.remove(os.path.join(self.path, filename))
 
view = sublime.active_window().new_file()
edit = view.begin_edit()
view.insert(edit, 0, content)
view.end_edit(edit)
self.saveView(view)
 
# Marks a view as modified
def add(self, view):
if not self.enabled:
return
 
id = view.buffer_id()
if view.file_name() == None and not view.is_scratch():
self.views[id] = view
elif id in self.views:
del self.views[id]
 
# Marks a view as having been closed
def remove(self, view):
if not self.enabled:
return
 
id = view.buffer_id()
if id in self.views:
del self.views[id]
 
def on_post_save(self, view):
self.remove(view)
self.timer.notify()
 
def on_close(self, view):
self.remove(view)
self.timer.notify()
 
def on_new(self, view):
self.add(view)
self.timer.notify()
 
def on_clone(self, view):
self.add(view)
self.timer.notify()
 
def on_modified(self, view):
self.add(view)
self.timer.notify()

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.