def next(self, length=None): if length == None: length = INFINITY if self.index < len(self.ops): next_op = self.ops[self.index] offset = self.offset next_op_length = op_length(next_op) if (length >= next_op_length - offset): length = next_op_length - offset self.index += 1 self.offset = 0 else: self.offset += length return_op = dict() if 'attributes' in next_op: return_op['attributes'] = next_op['attributes'] if 'delete' in next_op: return_op['delete'] = length elif 'retain' in next_op: return_op['retain'] = length elif 'insert' in next_op: if is_string(next_op['insert']): return_op['insert'] = next_op['insert'][offset:offset + length] else: return_op['insert'] = next_op['insert'] return return_op else: return {'retain': INFINITY}
def next(self, length=None): if length == None: length = INFINITY if self.index < len(self.ops): next_op = self.ops[self.index] offset = self.offset next_op_length = op_length(next_op) if (length >= next_op_length - offset): length = next_op_length - offset self.index += 1 self.offset = 0 else: self.offset += length return_op = dict() if 'attributes' in next_op: return_op['attributes'] = next_op['attributes'] if 'delete' in next_op: return_op['delete'] = length elif 'retain' in next_op: return_op['retain'] = length elif 'insert' in next_op: if is_string(next_op['insert']): return_op['insert'] = next_op['insert'][offset:offset+length] else: return_op['insert'] = next_op['insert'] return return_op else: return {'retain': INFINITY}
def transform(self, other, priority=True): self_iter = OpIterator(self.ops) other_iter = OpIterator(other.ops) delta = Delta() while self_iter.has_next() or other_iter.has_next(): if self_iter.peek_type() == 'insert' and ( priority or other_iter.peek_type() != 'insert'): delta.retain(op_length(self_iter.next())) elif other_iter.peek_type() == 'insert': delta.push(other_iter.next()) else: length = min(self_iter.peek_length(), other_iter.peek_length()) self_op = self_iter.next(length) other_op = other_iter.next(length) if 'delete' in self_op: continue elif 'delete' in other_op: delta.push(other_op) else: delta.retain( length, attr_transform(self_op.get('attributes'), other_op.get('attributes'), priority)) return delta.chop()
def slice(self, start=0, end=None): if end == None: end = INFINITY delta = Delta() self_iter = OpIterator(self.ops) index = 0 while (index < end) and self_iter.has_next(): if (index < start): next_op = self_iter.next(start - index) else: next_op = self_iter.next(end - index) delta.push(next_op) index += op_length(next_op) return delta
def transform(self, other, priority=True): self_iter = OpIterator(self.ops) other_iter = OpIterator(other.ops) delta = Delta() while self_iter.has_next() or other_iter.has_next(): if self_iter.peek_type() == 'insert' and (priority or other_iter.peek_type() != 'insert'): delta.retain(op_length(self_iter.next())) elif other_iter.peek_type() == 'insert': delta.push(other_iter.next()) else: length = min(self_iter.peek_length(), other_iter.peek_length()) self_op = self_iter.next(length) other_op = other_iter.next(length) if 'delete' in self_op: continue elif 'delete' in other_op: delta.push(other_op) else: delta.retain(length, attr_transform(self_op.get('attributes'), other_op.get('attributes'), priority)) return delta.chop()
def peek_length(self): if self.index < len(self.ops): # should never return 0 if our index is being managed correctly return op_length(self.ops[self.index]) - self.offset else: return INFINITY
def length(self): return sum([op_length(op) for op in self.ops])