1
0
Fork 0
mirror of https://github.com/topydo/topydo.git synced 2024-05-20 13:58:33 +00:00

edit: Don't move modified todo items to the end of file

Before this patch a `t edit ...` will remove todo items selected by
`...` and then do equivalent of `t add` with input from result of
editing. This works, but has the property that whenever a todo item is
edited, it is always moved till the end of todo.txt file.

This property creates noise and makes synchronization harder to implement for
some of us who uses VCS and different machines to maintain todo.txt .

-> Teach edit to preserve todo items in their places. Adjust existing
tests and add a couple more exercising cases where either new todo
items are added in the editor, or vice versa, removed in the editor.

/cc @mruwek
This commit is contained in:
Kirill Smelkov 2020-01-22 14:43:44 +03:00 committed by David Steele
parent 767bea58a0
commit 09438df104
3 changed files with 55 additions and 6 deletions

View file

@ -58,7 +58,7 @@ class EditCommandTest(CommandTest):
self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.print_todos(), u"Bar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a\nFoo id:1")
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBar p:1 @test\nBaz @test\nFo\u00f3B\u0105\u017a")
@mock.patch('topydo.commands.EditCommand._is_edited')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@ -75,7 +75,7 @@ class EditCommandTest(CommandTest):
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.errors, "")
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBaz @test\nFo\u00f3B\u0105\u017a\nLazy Cat")
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nLazy Cat\nBaz @test\nFo\u00f3B\u0105\u017a")
def test_edit03(self):
""" Throw an error after invalid todo number given as argument. """
@ -156,12 +156,49 @@ class EditCommandTest(CommandTest):
self.error, None)
command.execute()
expected = u"| 3| Lazy Cat\n| 4| Lazy Dog\n"
expected = u"| 2| Lazy Cat\n| 3| Lazy Dog\n"
self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.output, expected)
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nFo\u00f3B\u0105\u017a\nLazy Cat\nLazy Dog")
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nLazy Cat\nLazy Dog\nFo\u00f3B\u0105\u017a")
@mock.patch('topydo.commands.EditCommand._is_edited')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit_addnew(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited):
""" New todos are added in the process of editing. """
mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Bar (edited)'),
Todo('New1'),
Todo('New 2')]
mock_is_edited.return_value = True
command = EditCommand(["2"], self.todolist, self.out, self.error, None)
command.execute()
self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.print_todos(), u"Foo id:1\nBar (edited)\nBaz @test\nFo\u00f3B\u0105\u017a\nNew1\nNew 2")
@mock.patch('topydo.commands.EditCommand._is_edited')
@mock.patch('topydo.commands.EditCommand.EditCommand._todos_from_temp')
@mock.patch('topydo.commands.EditCommand.EditCommand._open_in_editor')
def test_edit_remove(self, mock_open_in_editor, mock_todos_from_temp, mock_is_edited):
""" Some todos are removed in the process of editing. """
mock_open_in_editor.return_value = 0
mock_todos_from_temp.return_value = [Todo('Foo (edited)')]
mock_is_edited.return_value = True
command = EditCommand(["1", "2"], self.todolist, self.out, self.error, None)
command.execute()
self.assertEqual(self.errors, "")
self.assertTrue(self.todolist.dirty)
self.assertEqual(self.todolist.print_todos(), u"Foo (edited)\nBaz @test\nFo\u00f3B\u0105\u017a")
@mock.patch.dict(os.environ, {'EDITOR': 'vi'})
@mock.patch('topydo.commands.EditCommand.check_call')

View file

@ -117,10 +117,15 @@ class EditCommand(MultiCommand):
new_todos = EditCommand._todos_from_temp(temp_todos)
if _is_edited(orig_mtime, temp_todos):
for todo in self.todos:
modified = list(zip(self.todos, new_todos))
for (todo, new_todo) in modified:
self.todolist.modify_todo(todo, new_todo.src)
self.out(self.printer.print_todo(todo))
for todo in self.todos[len(modified):]:
self.todolist.delete(todo, p_leave_tags=True)
for todo in new_todos:
for todo in new_todos[len(modified):]:
self.todolist.add_todo(todo)
self.out(self.printer.print_todo(todo))
else:

View file

@ -173,6 +173,13 @@ class TodoListBase(object):
# todo item couldn't be found, ignore
pass
def modify_todo(self, p_todo, p_new_source):
""" Modify source of a Todo item from the list. """
assert p_todo in self._todos
p_todo.set_source_text(p_new_source)
self._update_todo_ids()
self.dirty = True
def erase(self):
""" Erases all todos from the list. """
self._todos = []