Commit 211d1277 authored by Bram Schoenmakers's avatar Bram Schoenmakers

Add 'tag' subcommand.

parent 671c2aee
...@@ -35,6 +35,7 @@ from ListProjectCommand import ListProjectCommand ...@@ -35,6 +35,7 @@ from ListProjectCommand import ListProjectCommand
from PrettyPrinter import * from PrettyPrinter import *
from PriorityCommand import PriorityCommand from PriorityCommand import PriorityCommand
from SortCommand import SortCommand from SortCommand import SortCommand
from TagCommand import TagCommand
import TodoFile import TodoFile
import TodoList import TodoList
from Utils import escape_ansi from Utils import escape_ansi
...@@ -121,6 +122,7 @@ class CLIApplication(object): ...@@ -121,6 +122,7 @@ class CLIApplication(object):
'pri': PriorityCommand, 'pri': PriorityCommand,
'rm': DeleteCommand, 'rm': DeleteCommand,
'sort': SortCommand, 'sort': SortCommand,
'tag': TagCommand,
} }
args = arguments() args = arguments()
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from Command import *
import TodoList
from PrettyPrinter import pretty_print
from Utils import convert_todo_number, InvalidTodoNumberException
class TagCommand(Command):
def __init__(self, p_args, p_todolist,
p_out=lambda a: None,
p_err=lambda a: None,
p_prompt=lambda a: None):
super(TagCommand, self).__init__(p_args, p_todolist, p_out, p_err, p_prompt)
self.subsubcommand = None
self.todo = None
self.tag = None
self.value = None
self.values = []
try:
self.subsubcommand = self.argument(0)
number = convert_todo_number(self.argument(1))
self.todo = self.todolist.todo(number)
self.tag = self.argument(2)
self.current_values = self.todo.tag_values(self.tag)
self.value = self.argument(3)
except (InvalidCommandArgument, InvalidTodoNumberException, TodoList.InvalidTodoException):
pass
def _print(self):
self.out(pretty_print(self.todo, [self.todolist.pp_number()]))
def _choose(self):
"""
Returns the chosen number of the tag value to process (or "all")
"""
for i, value in enumerate(self.current_values):
self.out("%2d. %s" % (i + 1, value))
answer = self.prompt('Which value to remove? Enter number or "all": ')
if answer != "all":
try:
answer = int(answer) - 1
if answer < 0 or answer >= len(self.current_values):
answer = None
except ValueError:
answer = None
return answer
def _add(self):
self._set(True)
def _set_helper(self, p_force, p_old_value=""):
old_src = self.todo.source()
self.todo.set_tag(self.tag, self.value, p_force, p_old_value)
if old_src != self.todo.source():
self.todolist.set_dirty()
def _set(self, p_force_add=False):
if self.value == None:
self.error("Missing value for tag.")
self.error(self.usage())
else:
if len(self.current_values) > 1:
answer = self._choose()
if answer == "all":
for value in self.current_values:
self._set_helper(False, value)
elif answer != None and self.value != self.current_values[answer]:
self._set_helper(False, self.current_values[answer])
else: # if not self.todo.has_tag(self.tag, self.value):
self._set_helper(p_force_add)
self._print()
def _rm(self):
self.value = ""
self._set()
def execute(self):
if not super(TagCommand, self).execute():
return False
dispatch = {
"add": self._add,
"set": self._set,
"del": self._rm,
"rm": self._rm,
}
if self.subsubcommand in dispatch and self.todo and self.tag:
dispatch[self.subsubcommand]()
elif self.subsubcommand not in dispatch:
self.error(self.usage())
elif not self.todo:
self.error("Invalid todo number.")
def usage(self):
return """Synopsis:
tag (add|set) <NUMBER> <tag> <value>
tag rm <NUMBER> <tag> [value]"""
def help(self):
return """* add: Add a tag to the given todo.
* set: Changes a tag of the given todo.
* rm: Removes a tag from the given todo."""
...@@ -301,6 +301,9 @@ class TodoList(object): ...@@ -301,6 +301,9 @@ class TodoList(object):
def is_dirty(self): def is_dirty(self):
return self.dirty return self.dirty
def set_dirty(self):
self.dirty = True
def todos(self): def todos(self):
return self._todos return self._todos
......
# Topydo - A todo.txt client written in Python.
# Copyright (C) 2014 Bram Schoenmakers <me@bramschoenmakers.nl>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import CommandTest
import TagCommand
import TodoList
class TagCommandTest(CommandTest.CommandTest):
def setUp(self):
todos = [
"Foo",
"Bar due:2014-10-22",
"Baz due:2014-10-20",
"Fnord due:2014-10-20 due:2014-10-22",
]
self.todolist = TodoList.TodoList(todos)
def test_add_tag1(self):
command = TagCommand.TagCommand(["add", "1", "due", "2014-10-22"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.todolist.todo(1).source(), "Foo due:2014-10-22")
self.assertEquals(self.output, " 1 Foo due:2014-10-22\n")
self.assertEquals(self.errors, "")
self.assertTrue(self.todolist.is_dirty())
def test_add_tag2(self):
command = TagCommand.TagCommand(["add", "1", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Missing value for tag.\n" + command.usage() + "\n")
self.assertFalse(self.todolist.is_dirty())
def test_add_tag3(self):
command = TagCommand.TagCommand(["add", "2", "due", "2014-10-19"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.todolist.todo(2).source(), "Bar due:2014-10-22 due:2014-10-19")
self.assertEquals(self.output, " 2 Bar due:2014-10-22 due:2014-10-19\n")
self.assertEquals(self.errors, "")
self.assertTrue(self.todolist.is_dirty())
def test_add_tag4(self):
command = TagCommand.TagCommand(["add", "1", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Missing value for tag.\n" + command.usage() + "\n")
self.assertFalse(self.todolist.is_dirty())
def test_set_tag1(self):
command = TagCommand.TagCommand(["set", "1", "due", "2014-10-22"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 1 Foo due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_set_tag2(self):
command = TagCommand.TagCommand(["set", "1", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Missing value for tag.\n" + command.usage() + "\n")
def test_set_tag3(self):
command = TagCommand.TagCommand(["set", "2", "due", "2014-10-20"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 2 Bar due:2014-10-20\n")
self.assertEquals(self.errors, "")
def test_set_tag4(self):
command = TagCommand.TagCommand(["set", "3", "due", "2014-10-20"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 3 Baz due:2014-10-20\n")
self.assertEquals(self.errors, "")
def test_set_tag5(self):
command = TagCommand.TagCommand(["set", "4", "due", "2014-10-20"], self.todolist, self.out, self.error, lambda t: "all")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-20\n")
self.assertEquals(self.errors, "")
def test_set_tag6(self):
command = TagCommand.TagCommand(["set", "4", "due", "2014-10-20"], self.todolist, self.out, self.error, lambda t: "1")
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_set_tag7(self):
command = TagCommand.TagCommand(["set", "4", "due", "2014-10-20"], self.todolist, self.out, self.error, lambda t: "2")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-20\n")
self.assertEquals(self.errors, "")
def test_set_tag8(self):
command = TagCommand.TagCommand(["set", "4", "due", "2014-10-20"], self.todolist, self.out, self.error, lambda t: "")
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_set_tag9(self):
command = TagCommand.TagCommand(["set", "4", "due", "2014-10-20"], self.todolist, self.out, self.error, lambda t: "99")
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_rm_tag1(self):
command = TagCommand.TagCommand(["rm", "1", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 1 Foo\n")
self.assertEquals(self.errors, "")
def test_rm_tag2(self):
command = TagCommand.TagCommand(["rm", "2", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 2 Bar\n")
self.assertEquals(self.errors, "")
def test_rm_tag3(self):
command = TagCommand.TagCommand(["rm", "4", "due"], self.todolist, self.out, self.error, lambda t: "all")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord\n")
self.assertEquals(self.errors, "")
def test_rm_tag4(self):
command = TagCommand.TagCommand(["rm", "4", "due"], self.todolist, self.out, self.error, lambda t: "1")
command.execute()
self.assertTrue(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_rm_tag6(self):
command = TagCommand.TagCommand(["rm", "4", "due"], self.todolist, self.out, self.error, lambda t: "99")
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_rm_tag7(self):
command = TagCommand.TagCommand(["rm", "4", "due"], self.todolist, self.out, self.error, lambda t: "A")
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, " 1. 2014-10-20\n 2. 2014-10-22\n 4 Fnord due:2014-10-20 due:2014-10-22\n")
self.assertEquals(self.errors, "")
def test_rm_tag8(self):
command = TagCommand.TagCommand(["rm", "5", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number.\n")
def test_rm_tag9(self):
command = TagCommand.TagCommand(["rm", "A", "due"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, "Invalid todo number.\n")
def test_invalid_subsubcommand(self):
command = TagCommand.TagCommand(["foo", "bar"], self.todolist, self.out, self.error)
command.execute()
self.assertFalse(self.todolist.is_dirty())
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n")
def test_help(self):
command = TagCommand.TagCommand(["help"], self.todolist, self.out, self.error)
command.execute()
self.assertEquals(self.output, "")
self.assertEquals(self.errors, command.usage() + "\n\n" + command.help() + "\n")
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment