Dotfiles/sublime-text/Default/kill_ring.py
2014-05-12 18:57:15 +02:00

107 lines
3.1 KiB
Python

import sublime_plugin, sublime
class KillRing:
def __init__(self):
self.limit = 16
self.buffer = [None for i in xrange(self.limit)]
self.head = 0
self.len = 0
self.kill_points = []
self.kill_id = 0
def top(self):
return self.buffer[self.head]
def seal(self):
self.kill_points = []
self.kill_id = 0
def push(self, text):
self.head = (self.head + 1) % self.limit
self.buffer[self.head] = text
if self.len < self.limit:
self.len += 1
def add(self, view_id, text, regions, forward):
if view_id != self.kill_id:
# view has changed, ensure the last kill ring entry will not be
# appended to
self.seal()
begin_points = []
end_points = []
for r in regions:
begin_points.append(r.begin())
end_points.append(r.end())
if forward:
compare_points = begin_points
else:
compare_points = end_points
if compare_points == self.kill_points:
# Selection hasn't moved since the last kill, append/prepend the
# text to the current entry
if forward:
self.buffer[self.head] = self.buffer[self.head] + text
else:
self.buffer[self.head] = text + self.buffer[self.head]
else:
# Create a new entry in the kill ring for this text
self.push(text)
self.kill_points = begin_points
self.kill_id = view_id
def get(self, index):
return self.buffer[(self.head + index) % self.limit]
def __len__(self):
return self.len
kill_ring = KillRing()
class YankCommand(sublime_plugin.TextCommand):
def run(self, edit):
kill_ring.seal()
text = kill_ring.top()
lines = text.splitlines()
regions = [r for r in self.view.sel()]
regions.reverse()
if len(regions) > 1 and len(regions) == len(lines):
# insert one line from the top of the kill ring at each
# corresponding selection
for i in xrange(len(regions)):
s = regions[i]
line = lines[i]
num = self.view.insert(edit, s.begin(), line)
self.view.erase(edit, sublime.Region(s.begin() + num,
s.end() + num))
else:
# insert the top of the kill ring at each selection
for s in regions:
num = self.view.insert(edit, s.begin(), text)
self.view.erase(edit, sublime.Region(s.begin() + num,
s.end() + num))
def is_enabled(self):
return len(kill_ring) > 0
class AddToKillRingCommand(sublime_plugin.TextCommand):
def run(self, edit, forward):
delta = 1
if not forward:
delta = -1
text = []
regions = []
for s in self.view.sel():
if s.empty():
s = sublime.Region(s.a, s.a + delta)
text.append(self.view.substr(s))
regions.append(s)
kill_ring.add(self.view.id(), "\n".join(text), regions, forward)