231 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			231 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import sublime
 | |
| import sublime_plugin
 | |
| 
 | |
| 
 | |
| class HistoryList(list):
 | |
|     """
 | |
|     List type for storing the history.
 | |
|     Maintains a "pointer" to the current clipboard item
 | |
|     """
 | |
|     registers = {}
 | |
|     SIZE = 256
 | |
|     __index = 0
 | |
| 
 | |
|     def show(self):
 | |
|         ret = ""
 | |
|         ret += " CLIPBOARD HISTORY (%d)\n" % len(self)
 | |
|         ret += "====================%s==\n" % ("=" * len(str(len(self))))
 | |
|         for i, item in enumerate(self):
 | |
|             if i == self.__index:
 | |
|                 ret += '--> '
 | |
|             else:
 | |
|                 ret += '    '
 | |
|             item = item.replace("\t", '\\t')
 | |
|             item = item.replace("\r\n", "\n")
 | |
|             item = item.replace("\r", "\n")
 | |
|             item = item.replace("\n", "\n" + '       > ')
 | |
|             ret += u'{i:>3}. {item}\n'.format(i=str(i + 1)[-3:], item=item)
 | |
|         return ret
 | |
| 
 | |
|     def show_registers(self):
 | |
|         ret = ""
 | |
|         ret += " CLIPBOARD REGISTERS (%d)\n" % len(self.registers.items())
 | |
|         ret += "=====================%s==\n" % ("=" * len(str(len(self.registers.items()))))
 | |
|         for key, item in self.registers.iteritems():
 | |
|             item = item.replace("\t", '\\t')
 | |
|             item = item.replace("\r\n", "\n")
 | |
|             item = item.replace("\r", "\n")
 | |
|             item = item.replace("\n", "\n" + ' > ')
 | |
|             ret += u'{key:<1}: {item}\n'.format(key=key, item=item)
 | |
|         return ret
 | |
| 
 | |
|     def register(self, register, *args):
 | |
|         if args:
 | |
|             if len(args) == 1:
 | |
|                 copy = args[0]
 | |
|             else:
 | |
|                 copy = "\n".join(args)
 | |
|             self.registers[register] = copy
 | |
|             copy = copy.replace("\t", "\\t")
 | |
|             copy = copy.replace("\n", "\\n")
 | |
|             copy = copy.replace("\r", "\\r")
 | |
|             sublime.status_message('Set Clipboard Register "{0}" to "{1}"'.format(register, copy))
 | |
|         else:
 | |
|             return self.registers[register]
 | |
| 
 | |
|     def append(self, item):
 | |
|         """
 | |
|         Appends to the history only if it isn't the current item.
 | |
|         """
 | |
|         if not self or self[self.__index] != item:
 | |
|             self.insert(0, item)
 | |
|             self.__index = 0
 | |
|             if len(self) > self.SIZE:
 | |
|                 del self[self.SIZE:]
 | |
| 
 | |
|     def current(self):
 | |
|         if len(self) == 0:
 | |
|             return None
 | |
|         return self[self.__index]
 | |
| 
 | |
|     def at(self, idx):
 | |
|         self.__index = (idx if idx < len(self) else 0)
 | |
|         self.status()
 | |
| 
 | |
|     def next(self):
 | |
|         if self.__index > 0:
 | |
|             self.__index -= 1
 | |
|         self.status()
 | |
| 
 | |
|     def previous(self):
 | |
|         if self.__index < len(self) - 1:
 | |
|             self.__index += 1
 | |
|         self.status()
 | |
| 
 | |
|     def first(self):
 | |
|         """"first" actually kind of means "last", since this is a FIFO stack"""
 | |
|         self.__index = len(self) - 1
 | |
|         self.status()
 | |
| 
 | |
|     def last(self):
 | |
|         """"last" actually kind of means "first", since this is a FIFO stack"""
 | |
|         self.__index = 0
 | |
|         self.status()
 | |
| 
 | |
|     def status(self):
 | |
|         copy = self.current()
 | |
|         copy = copy.replace("\t", "\\t")
 | |
|         copy = copy.replace("\n", "\\n")
 | |
|         copy = copy.replace("\r", "\\r")
 | |
|         sublime.status_message(u'Set Clipboard to "{copy}"'.format(copy=copy))
 | |
|         sublime.set_clipboard(self.current())
 | |
| 
 | |
| 
 | |
| HISTORY = HistoryList([sublime.get_clipboard()])
 | |
| 
 | |
| 
 | |
| def append_clipboard():
 | |
|     # append the contents of the clipboard to the history
 | |
|     HISTORY.append(sublime.get_clipboard())
 | |
| 
 | |
| 
 | |
| class ClipboardManagerPaste(sublime_plugin.TextCommand):
 | |
|     def run(self, edit, indent=False):
 | |
|         if indent:
 | |
|             self.view.run_command('paste_and_indent')
 | |
|         else:
 | |
|             self.view.run_command('paste')
 | |
| 
 | |
| 
 | |
| class ClipboardManagerCut(sublime_plugin.TextCommand):
 | |
|     def run(self, edit):
 | |
|         # First run sublime's command to extract the selected text.
 | |
|         # This will set the cut/copy'd data on the clipboard which we can easily steal without recreating the cut/copy logic.
 | |
|         self.view.run_command('cut')
 | |
|         append_clipboard()
 | |
|         self.view.window().run_command('clipboard_manager_show', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerCopy(sublime_plugin.TextCommand):
 | |
|     def run(self, edit):
 | |
|         self.view.run_command('copy')
 | |
|         append_clipboard()
 | |
|         self.view.window().run_command('clipboard_manager_show', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerCopyToRegister(sublime_plugin.TextCommand):
 | |
|     def run(self, edit, register):
 | |
|         self.view.run_command('copy')
 | |
|         HISTORY.register(register, sublime.get_clipboard())
 | |
|         self.view.window().run_command('clipboard_manager_show_registers', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerPasteFromRegister(sublime_plugin.TextCommand):
 | |
|     def run(self, edit, register):
 | |
|         sublime.set_clipboard(HISTORY.register(register))
 | |
|         self.view.run_command('paste')
 | |
| 
 | |
| 
 | |
| class ClipboardManagerNext(sublime_plugin.TextCommand):
 | |
|     def run(self, edit):
 | |
|         HISTORY.next()
 | |
|         self.view.window().run_command('clipboard_manager_show', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerNextAndPaste(sublime_plugin.TextCommand):
 | |
|     def run(self, edit, indent=False):
 | |
|         HISTORY.next()
 | |
|         if indent:
 | |
|             self.view.run_command('paste_and_indent')
 | |
|         else:
 | |
|             self.view.run_command('paste')
 | |
|         self.view.window().run_command('clipboard_manager_show', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerPrevious(sublime_plugin.TextCommand):
 | |
|     def run(self, edit):
 | |
|         HISTORY.previous()
 | |
|         self.view.window().run_command('clipboard_manager_show', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerPreviousAndPaste(sublime_plugin.TextCommand):
 | |
|     def run(self, edit, indent=False):
 | |
|         HISTORY.previous()
 | |
|         if indent:
 | |
|             self.view.run_command('paste_and_indent')
 | |
|         else:
 | |
|             self.view.run_command('paste')
 | |
|         self.view.window().run_command('clipboard_manager_show', {'show': False})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerShow(sublime_plugin.WindowCommand):
 | |
|     def run(self, show=True):
 | |
|         v = self.window.get_output_panel('clipboard_manager')
 | |
|         e = v.begin_edit('clipboard_manager')
 | |
|         v.replace(e, sublime.Region(0, v.size()), '')
 | |
|         v.insert(e, 0, HISTORY.show())
 | |
|         v.end_edit(e)
 | |
|         if show:
 | |
|             self.window.run_command('show_panel', {'panel': 'output.clipboard_manager'})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerShowRegisters(sublime_plugin.WindowCommand):
 | |
|     def run(self, show=True):
 | |
|         v = self.window.get_output_panel('clipboard_manager')
 | |
|         e = v.begin_edit('clipboard_manager')
 | |
|         v.replace(e, sublime.Region(0, v.size()), '')
 | |
|         v.insert(e, 0, HISTORY.show_registers())
 | |
|         v.end_edit(e)
 | |
|         if show:
 | |
|             self.window.run_command('show_panel', {'panel': 'output.clipboard_manager'})
 | |
| 
 | |
| 
 | |
| class ClipboardManagerChooseAndPaste(sublime_plugin.TextCommand):
 | |
|     def run(self, edit):
 | |
|         def format(line):
 | |
|             return line.replace('\n', '\\n')[:64]
 | |
| 
 | |
|         lines = []
 | |
|         line_map = {}
 | |
|         # filter out duplicates, keeping the first instance, and format
 | |
|         for i, line in enumerate(HISTORY):
 | |
|             if i == HISTORY.index(line):
 | |
|                 line_map[len(lines)] = i
 | |
|                 lines.append(format(line))
 | |
| 
 | |
|         def on_done(idx):
 | |
|             if idx >= 0:
 | |
|                 idx = line_map[idx]
 | |
|                 HISTORY.at(idx)
 | |
|                 self.view.run_command('paste')
 | |
| 
 | |
|         if lines:
 | |
|             sublime.active_window().show_quick_panel(lines, on_done)
 | |
|         else:
 | |
|             sublime.status_message('Nothing in history')
 | |
| 
 | |
| 
 | |
| class ClipboardManagerEventListener(sublime_plugin.EventListener):
 | |
|     def on_activated(self, view):
 | |
|         append_clipboard()
 |