def __init__(self, script_str=''): self.code = GapBuffer(script_str) self.text_inserted = Event() self.range_deleted = Event() self.lock = threading.RLock() self.marks = {} self.name_counter = 0
class TextTests(unittest.TestCase): def setUp(self): self.gapbuffer = GapBuffer() def tearDown(self): pass def test_empty_buffer_gives_empty_text(self): self.assertEqual("", self.gapbuffer.get_text())
class Script(object): """Represents a script in the editor""" def __init__(self, script_str=''): self.code = GapBuffer(script_str) self.text_inserted = Event() self.range_deleted = Event() self.lock = threading.RLock() self.marks = {} self.name_counter = 0 def add_mark(self, position, gravity='left', name=None): """Adds a mark in the script which maintains a relative position when text is added/deleted. Thread safe. """ with self.lock: if not name: name = 'mark %d' % self.name_counter self.name_counter += 1 if name in self.marks: raise Excpetion('name %s is already used' % name) self.marks[name] = ScriptMark(position, self, gravity, name) return name def remove_mark(self, name): """Removes the given mark""" with self.lock: if not name in self.marks: raise Excpetion('mark %s is not found' % name) self.marks[name].invalidate() del self.marks[name] def clear_marks(self): """Clears all marks""" with self.lock: names_to_delete = self.marks.keys() for name in names_to_delete: self.remove_mark(name) def mark_position(self, name): """Gets the position for the given mark Thread safe. """ with self.lock: if not name in self.marks: raise Excpetion('mark %s is not found' % name) return self.marks[name].position def insert_text(self, position, text, sender=None): """Inserts text to the script and calls the text_inserted event. Thread safe. """ #logging.debug('inserted text to script: %s', text) with self.lock: text = str(text) if type(position) != int: position = self.mark_position(position) self.code.insert(position, text) self.text_inserted(position, text, sender) def delete_range(self, start=None, end=None, sender=None): """Delete text from the script and calls the text_deleted event. Thread safe. """ with self.lock: #logging.debug('deleting from %s to %s' % (start, end)) start, end = self._fix_start_end(start, end) #logging.debug('deleted: %s' % self.code[start:end]) del self.code[start:end] self.range_deleted(start, end, sender) def clear(self, sender=None): """Clears the script. Thread safe. """ with self.lock: self.delete_range(0, len(self.code), sender) self.code.slim() def _fix_start_end(self, start, end): with self.lock: if not start: start = 0 if not end: end = len(self.code) if type(start) != int: start = self.mark_position(start) if type(end) != int: end = self.mark_position(end) return start, end def get_code_as_str(self, start=None, end=None): """Gets the code as a string. Thread safe. """ with self.lock: start, end = self._fix_start_end(start, end) return str(self.code[start:end])
def setUp(self): self.gapbuffer = GapBuffer()
def test_cursor_cant_be_moved_forward_after_only_inserts_in_incorrectly_sized_buffer( self): self.gapbuffer = GapBuffer(2) self.gapbuffer.insert("abc") self.assertFalse(self.gapbuffer.cursor_can_move_forward())
def test_cursor_cant_be_moved_forward_after_only_inserts(self): self.gapbuffer = GapBuffer(4) self.gapbuffer.insert('a') self.assertFalse(self.gapbuffer.cursor_can_move_forward())
def test_inser_on_incorrectly_sized_buffer(self): self.gapbuffer = GapBuffer(2) self.gapbuffer.insert("hell\no") self.assertEqual("hell\no", self.gapbuffer.get_text())
class InsertTests(unittest.TestCase): def setUp(self): self.gapbuffer = GapBuffer() def tearDown(self): pass def test_insert_one_character(self): self.gapbuffer.insert('a') self.assertEqual("a", self.gapbuffer.get_text()) def test_insert_one_characterAsString(self): self.gapbuffer.insert("a") self.assertEqual("a", self.gapbuffer.get_text()) def test_insert_multiple_character(self): self.gapbuffer.insert('a') self.gapbuffer.insert('b') self.gapbuffer.insert('c') self.assertEqual("abc", self.gapbuffer.get_text()) def test_insert_with_multi_character_string(self): self.gapbuffer.insert("abc") self.assertEqual("abc", self.gapbuffer.get_text()) def test_insert_with_one_special_character(self): self.gapbuffer.insert('\n') self.assertEqual('\n', self.gapbuffer.get_text()) def test_insert_With_multiple_special_characters(self): self.gapbuffer.insert('\t') self.gapbuffer.insert('\n') self.assertEqual("\t\n", self.gapbuffer.get_text()) def test_insert_with_multiple_special_character_string(self): self.gapbuffer.insert("\t\n") self.assertEqual("\t\n", self.gapbuffer.get_text()) def test_insert_on_correct_sized_buffer(self): self.gapbuffer = GapBuffer(6) self.gapbuffer.insert("hell\no") self.assertEqual("hell\no", self.gapbuffer.get_text()) def test_inser_on_incorrectly_sized_buffer(self): self.gapbuffer = GapBuffer(2) self.gapbuffer.insert("hell\no") self.assertEqual("hell\no", self.gapbuffer.get_text()) def testCursorHasCorrectPositionAfterInsert(self): self.assertEqual(0, self.gapbuffer.get_cursor_position()) self.gapbuffer.insert('a') self.assertEqual(1, self.gapbuffer.get_cursor_position()) def test_cursor_has_correct_position_after_multiple_inserts(self): self.assertEqual(0, self.gapbuffer.get_cursor_position()) self.gapbuffer.insert('a') self.gapbuffer.insert('b') self.assertEqual(2, self.gapbuffer.get_cursor_position()) def test_cursor_has_correct_position_after_insert_in_middle_of_buffer( self): self.gapbuffer.insert("abef") self.gapbuffer.move_cursor_backward(2) self.gapbuffer.insert("cd") self.assertEqual(4, self.gapbuffer.get_cursor_position()) def test_cursor_has_correct_position_after_multi_character_string_insert( self): self.assertEqual(0, self.gapbuffer.get_cursor_position()) self.gapbuffer.insert("abc") self.assertEqual(3, self.gapbuffer.get_cursor_position()) def test_insert_in_middle_of_buffer_after_moving_cursor(self): self.gapbuffer.insert("acd") self.gapbuffer.move_cursor_backward(2) self.gapbuffer.insert('b') self.assertEqual("abcd", self.gapbuffer.get_text()) def test_insert_at_start_of_buffer_after_moving_cursor(self): self.gapbuffer.insert("bcd") self.gapbuffer.move_cursor_backward(3) self.gapbuffer.insert('a') self.assertEqual("abcd", self.gapbuffer.get_text())
class DeleteTests(unittest.TestCase): def setUp(self): self.gapbuffer = GapBuffer() def test_deleting_single_character(self): self.gapbuffer.insert("a") self.gapbuffer.delete() self.assertEqual("", self.gapbuffer.get_text()) def test_deleting_multiple_characters(self): self.gapbuffer.insert("abcd") self.gapbuffer.delete() self.gapbuffer.delete() self.assertEqual("ab", self.gapbuffer.get_text()) def test_delete_after_moving_cursor(self): self.gapbuffer.insert("abcd") self.gapbuffer.move_cursor_backward(2) self.gapbuffer.delete() self.assertEqual("acd", self.gapbuffer.get_text()) def test_cursor_has_correct_position_after_single_delete(self): self.gapbuffer.insert("abc") self.gapbuffer.delete() self.assertEqual(2, self.gapbuffer.get_cursor_position()) def test_cursor_has_correct_position_after_multiple_delete(self): self.gapbuffer.insert("abc") self.gapbuffer.delete() self.gapbuffer.delete() self.assertEqual(1, self.gapbuffer.get_cursor_position()) def test_cursor_has_correct_position_after_being_moved_and_delete(self): self.gapbuffer.insert("abcd") self.gapbuffer.move_cursor_backward(2) self.gapbuffer.delete() self.assertEqual(1, self.gapbuffer.get_cursor_position())
class CursorMovementTests(unittest.TestCase): def setUp(self): self.gapbuffer = GapBuffer() def test_cursor_position_with_new_buffer_is_zero(self): self.assertEqual(0, self.gapbuffer.get_cursor_position()) def test_cursor_cant_be_moved_forward_with_empty_buffer(self): self.assertFalse(self.gapbuffer.cursor_can_move_forward()) def test_cursor_cant_be_moved_backward_with_empty_buffer(self): self.assertFalse(self.gapbuffer.cursor_can_move_backward()) def test_cursor_cant_be_moved_forward_once_with_emtpy_buffer(self): self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_forward) self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_forward, 1) def test_cursor_cant_be_moved_forward_an_arbitrary_amount_with_empty_buffer( self): #3 and 5 are arbitrary constants here self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_forward, 3) self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_forward, 5) def test_cursor_cant_be_moved_backward_once_with_empty_buffer(self): self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_backward) self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_backward, 1) def test_cursor_cant_be_moved_backward_an_arbitrary_amount_with_empty_buffer( self): self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_backward, 3) self.assertRaises(CursorOutOfBoundsException, self.gapbuffer.move_cursor_backward, 5) def test_cursor_can_be_moved_backwards_after_insert(self): self.gapbuffer.insert('a') self.assertTrue(self.gapbuffer.cursor_can_move_backward()) def test_moving_cursor_backwards_after_insert(self): self.gapbuffer.insert('a') self.assertEqual(1, self.gapbuffer.get_cursor_position()) self.gapbuffer.move_cursor_backward() self.assertEqual(0, self.gapbuffer.get_cursor_position()) def test_moving_cursor_backwards_more_than_one_position_after_insert(self): self.gapbuffer.insert("abc") self.assertEqual(3, self.gapbuffer.get_cursor_position()) self.gapbuffer.move_cursor_backward(2) self.assertEqual(1, self.gapbuffer.get_cursor_position()) self.gapbuffer.move_cursor_backward(1) self.assertEqual(0, self.gapbuffer.get_cursor_position()) def test_cursor_cant_be_moved_forward_after_only_inserts(self): self.gapbuffer = GapBuffer(4) self.gapbuffer.insert('a') self.assertFalse(self.gapbuffer.cursor_can_move_forward()) def test_cursor_cant_be_moved_forward_after_only_inserts_in_incorrectly_sized_buffer( self): self.gapbuffer = GapBuffer(2) self.gapbuffer.insert("abc") self.assertFalse(self.gapbuffer.cursor_can_move_forward()) def test_moving_cursor_forward_once_after_insert_and_moving_backward(self): self.gapbuffer.insert('a') self.gapbuffer.move_cursor_backward() self.gapbuffer.move_cursor_forward() self.assertEqual(1, self.gapbuffer.get_cursor_position()) def test_moving_cursor_forwards_more_than_one_position_after_inserts_and_moving_backwards( self): self.gapbuffer.insert("abc") self.gapbuffer.move_cursor_backward(3) self.gapbuffer.move_cursor_forward(2) self.assertEqual(2, self.gapbuffer.get_cursor_position())