about summary refs log tree commit diff stats
path: root/html/ex3.png
Commit message (Expand)AuthorAgeFilesLines
* 5485 - promote SubX to top-levelKartik Agaram2019-07-271-0/+0
d='n17' href='#n17'>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 129 130 131 132 133 134
# Copyright (C) 2009-2013  Roman Zimbelmann <hut@lepus.uberspace.de>
# 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) > max(self.maxlen - 1, 0):
            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]