summary refs log tree commit diff stats
path: root/cmd
ModeNameSize
d---------cetus-bing41log stats plain
d---------cetus-nasa41log stats plain
'#n22'>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 129 130 131 132 133 134
# Copyright (C) 2009, 2010, 2011  Roman Zimbelmann <romanz@lavabit.com>
# This software is distributed under the terms of the GNU GPL version 3.

# TODO: rewrite to use deque instead of list

class HistoryEmptyException(Exception):
	pass

class History(object):
	def __init__(self, maxlen=None, unique=True):
		if isinstance(maxlen, History):
			self._history = list(maxlen._history)
			self._index = maxlen._index
			self.maxlen = maxlen.maxlen
			self.unique = maxlen.unique
		else:
			self._history = []
			self._index = 0
			self.maxlen = maxlen
			self.unique = unique

	def add(self, item):
		# Remove everything after index
		if self._index < len(self._history) - 2:
			del self._history[:self._index+1]
		# Remove Duplicates
		if self.unique:
			try:
				self._history.remove(item)
			except:
				pass
		else:
			if self._history and self._history[-1] == item:
				del self._history[-1]
		# Remove first if list is too long
		if len(self._history) > self.maxlen - 1:
			del self._history[0]
		# Append the item and fast forward
		self._history.append(item)
		self._index = len(self._history) - 1

	def modify(self, item, unique=False):
		if self._history and unique:
			try:
				self._history.remove(item)
				self._index -= 1
			except:
				pass
		try:
			self._history[self._index] = item
		except IndexError:
			self.add(item)

	def rebase(self, other_history):
		assert isinstance(other_history, History)
		index_offset = len(self._history) - self._index
		self._history[:self._index] = list(other_history._history)
		if len(self._history) > self.maxlen:
			self._history = self._history[-self.maxlen:]
		self._index = len(self._history) - index_offset

	def __len__(self):
		return len(self._history)

	def current(self):
		if self._history:
			return self._history[self._index]
		else:
			raise HistoryEmptyException

	def top(self):
		try:
			return self._history[-1]
		except IndexError:
			raise HistoryEmptyException()

	def bottom(self):
		try:
			return self._history[0]
		except IndexError:
			raise HistoryEmptyException()

	def back(self):
		self._index -= 1
		if self._index < 0:
			self._index = 0
		return self.current()

	def move(self, n):
		self._index += n
		if self._index > len(self._history) - 1:
			self._index = len(self._history) - 1
		if self._index < 0:
			self._index = 0
		return self.current()

	def search(self, string, n):
		if n != 0 and string:
			step = n > 0 and 1 or -1
			i = self._index
			steps_left = steps_left_at_start = int(abs(n))
			while steps_left:
				i += step
				if i >= len(self._history) or i < 0:
					break
				if self._history[i].startswith(string):
					steps_left -= 1
			if steps_left != steps_left_at_start:
				self._index = i
		return self.current()

	def __iter__(self):
		return self._history.__iter__()

	def next(self):
		return self._history.next()

	def forward(self):
		if self._history:
			self._index += 1
			if self._index > len(self._history) - 1:
				self._index = len(self._history) - 1
		else:
			self._index = 0
		return self.current()

	def fast_forward(self):
		if self._history:
			self._index = len(self._history) - 1
		else:
			self._index = 0

	def _left(self):  # used for unit test
		return self._history[0:self._index+1]