summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Brox <t@tobixen.no>2015-05-18 06:41:48 +0200
committerTobias Brox <t@tobixen.no>2015-05-18 06:41:48 +0200
commit05a30e0849ae3fe181fee0c49cede3c62d96ff4d (patch)
treebdb36022faeca5ee48bec3f7ff92adddf98af468
parentfea55cd46500148a61248488423f6492e13957fd (diff)
downloadcalendar-cli-05a30e0849ae3fe181fee0c49cede3c62d96ff4d.zip
new options for selecting tasks: --overdue and --hide-future. Attempt to get comma-separated lists to work. Looked through the documentation a bit. Documented some of the ugly one-liners I'm currently using to manage agendas and task lists
-rw-r--r--EXAMPLES22
-rw-r--r--TASK_MANAGEMENT.md24
-rwxr-xr-xcalendar-cli.py19
3 files changed, 51 insertions, 14 deletions
diff --git a/EXAMPLES b/EXAMPLES
new file mode 100644
index 0000000..1c79725
--- /dev/null
+++ b/EXAMPLES
@@ -0,0 +1,22 @@
+TODO: clean this up a bit
+
+Eventually I'd like to make calendar-cli easier to use, so some of the "external logic" in those examples will eventually be moved into the tool itself. Anyway, some of the power of having a command-line utility is that it's possible to do just anything ...
+
+## Take out a personal agenda from different calendar sources:
+for section in pp seb house default work holidays ; do ./calendar-cli.py --config-section $section calendar agenda --agenda-days 20; done | sort ; for section in seb house default work-tasks pp-tasks ; do echo $section; ./calendar-cli.py --config-section $section todo --limit 10 --hide-parent list ; done ## AGENDA
+
+## Interactively set categories on uncategorized tasks:
+cd ~/calendar-cli/ ; { ./calendar-cli.py todo list --list-categories | perl -pe 's/^/# /' ; ./calendar-cli.py todo --nocategories list --todo-template='./calendar-cli.py todo --todo-uid={uid} edit --set-categories=foo # {summary}' ; } > /tmp/nocat ; $EDITOR /tmp/nocat ; . /tmp/nocat
+
+## Interactively mark tasks as completed:
+cd ~/calendar-cli/ ; { ./calendar-cli.py todo --hide-parents --limit 10 list --todo-template='# ./calendar-cli.py todo --todo-uid={uid} complete # {summary}' ; } > /tmp/tocomplete ; $EDITOR /tmp/tocomplete ; . /tmp/tocomplete
+
+## Interactively mark tasks as completed, with category:
+CAT=keyboard ; cd ~/calendar-cli/ ; { ./calendar-cli.py todo --hide-parents --categories=$CAT --limit 10 list --todo-template='# ./calendar-cli.py todo --todo-uid={uid} complete # {summary}' ; } > /tmp/tocomplete ; $EDITOR /tmp/tocomplete ; . /tmp/tocomplete
+
+## Set more realistic due-dates on overdue tasks
+cd ~/calendar-cli/ ; { ./calendar-cli.py todo --overdue list --todo-template='./calendar-cli.py todo --todo-uid={uid} postpone --due "in 2d" # {summary}' ; } > /tmp/toprocrastinate ; $EDITOR /tmp/toprocrastinate ; . /tmp/toprocrastinate
+
+## Clean the list a bit by procrastinating tasks (this includes the overdue)
+cd ~/calendar-cli/ ; { ./calendar-cli.py todo --hide-future list --todo-template='./calendar-cli.py todo --todo-uid={uid} postpone "in 5d" # {summary}' ; } > /tmp/toprocrastinate ; $EDITOR /tmp/toprocrastinate ; . /tmp/toprocrastinate
+
diff --git a/TASK_MANAGEMENT.md b/TASK_MANAGEMENT.md
index 977b2b1..a137d56 100644
--- a/TASK_MANAGEMENT.md
+++ b/TASK_MANAGEMENT.md
@@ -5,10 +5,12 @@ While the RFC does draw some lines on what fields are admissable in the todo-ent
As of 2015-04, this document is just a collection of random thoughts on how to organize task lists. I haven't done much research in how different software packages handles tasks, nor do I have much experience with managing task lists. Also, calendar-cli is not really ready yet.
-Calendar
---------
+Calendar scope
+--------------
+
+Different categories of tasks can be put into different calendars (and even different caldav servers).
-When should you make another calendar/task list and when does it make sense to keep things in the same calendar?
+I believe it's best to keep as few calendars as possible, and rather use i.e. the categories field for splitting different types of tasks.
As you can give access rights to other people for a whole caldav calendar (or "task list"), it makes sense to use the calendar level to control access rights. You would typically like to have one calendar where your family can view/add tasks, other for work, perhaps separate calendars for separate projects at work if different projects involves different people, etc.
@@ -44,22 +46,20 @@ When to use location or geo, and when to use category? I think that for the sup
Pending-Dependent
-----------------
-If one task A cannot be done without task B being done first, we say that A depends on B. It may make sense to hide A from todolists, or maybe fade it away. It may also make sense to push the due date for B such that there is a chance to get A done before it's due time.
+If task A cannot be done without task B being done first, we say that A depends on B. It may make sense to hide A from todolists, or maybe fade it away. It may also make sense to ensure the due date for B is before the due date for A.
The VTODO-standard does not support this kind of relationship, but it's possible to use parent-child. The parent will then be the dependent, and the child will be the pending.
Parent-child relationship
-------------------------
-This is not supported by calendar-cli as of today - but one can make a hierarchical task list. It makes a lot of sense when having a big task that can be split up in subtasks. Say, the task may be "build a bicycle shed". That does take quite some planning, purchases and work, so one will definitively want to break it up in subtasks. Ordering such a thing by categories is probably not so productive.
-
-What about the shopping list? "Buy squash" seems to be a subtask of "buy vegetables" which again may be a subtask of "go shopping at the supermarket" - but I think it makes more sense to use categories for that purpose. There are two differences between the supermarket shopping and the bicycle shed ...
+With the parent-child relationship one can make a hierarchical task list. It makes a lot of sense when having a big task that can be split up in subtasks. Say, the task may be "build a bicycle shed". That does take quite some planning, purchases and work, so one will definitively want to break it up in subtasks. Ordering such a thing by categories is probably not so productive.
-* Building the bicycle shed serves a purpose for it's own sake. You're going to buy planks for building the shed, you're not building a shed to buy planks.
+What about the shopping list? "Buy squash" seems to be a subtask of "buy vegetables" which again may be a subtask of "go shopping at the supermarket" - but I think it makes more sense to use categories for that purpose ...
-* "Go to the shop" is not a task for it's own sake - you'd probably not first consider "I need to go to the shop, let's add that to the task list" and then later "According to my task list, I need to go to the shop. Let's try to make a list of what I need there". It's more likely that you discover you're running out of sugar and then decide to add "buy sugar" to the shopping list - and you'll go to the shop because you need to buy sugar, you're not buying sugar because you need to go to the shop.
+* Different causality - building the bicycle shed serves a purpose for it's own sake. You're going to buy planks for building the shed, you're not building a shed to buy planks.
-* Multiple parents may not be that trivial - you may have many different projects that requires you to buy planks.
+* You'd first add "build a shed" on the todo-list and then try to plan and see what subtasks are needed. While one may first add "go to the shop" and then start thinking what to buy in the shop, it probably makes more sense to add "buy sugar" to the list when you see you're running short on sugar, or when you're planning to buy a cake.
Recurring tasks
---------------
@@ -73,9 +73,9 @@ There can be only one status and one complete-date for a vtodo, no matter if it'
dtstart vs due vs duration
--------------------------
-I my opinion, dtstart is the earliest time you expect to start working with the vtodo, maybe even the earliest time it's possible to start. One may want to postpone dtstart frequently.
+I my opinion, dtstart is the earliest time you expect to start working with the vtodo, maybe even the earliest time it's possible to start. Passing the dtstart doesn't mean you need to drop everything else and start working on the task immediately. You'd want to postpone the dtstart just to unclutter the todo-list.
-due is the time/date when the task has to be completed, come hell or high water. It should (in most cases) not be postponed.
+Due is the time/date when the task has to be completed, come hell or high water. It should probably not be postponed.
Different task list implementations may behave differently, most of them is probably only concerned with the due date.
diff --git a/calendar-cli.py b/calendar-cli.py
index a7ce245..31cc68b 100755
--- a/calendar-cli.py
+++ b/calendar-cli.py
@@ -332,12 +332,21 @@ def todo_add(caldav_conn, args):
rt.value = str(uid)
t.save()
- for attr in vtodo_txt_one + vtodo_txt_many:
+ for attr in vtodo_txt_one:
if attr == 'summary':
continue
val = getattr(args, 'set_'+attr)
if val:
todo.add(attr, val)
+ ## TODO: this doesn't currently work quite the way we'd like it to
+ ## work (it adds to lines to the ical, and vobject cares only
+ ## about one of them), and if we do get it to work, we'd like to
+ ## refactor and get the same logic in the edit-function
+ for attr in vtodo_txt_many:
+ val = getattr(args, 'set_'+attr)
+ if val:
+ vals = val.split(',')
+ todo.add(attr, vals)
cal.add_component(todo)
_calendar_addics(caldav_conn, cal.to_ical(), uid, args)
print("Added todo item with uid=%s" % uid)
@@ -407,7 +416,7 @@ def todo_select(caldav_conn, args):
## TODO: we're fetching everything from the server, and then doing the filtering here. It would be better to let the server do the filtering, though that requires library modifications.
## TODO: current release of the caldav library doesn't support the multi-key sort_keys attribute. The try-except construct should be removed at some point in the future, when caldav 0.5 is released.
try:
- tasks = find_calendar(caldav_conn, args).todos(sort_keys=('dtstart', 'due', 'priority'))
+ tasks = find_calendar(caldav_conn, args).todos(sort_keys=('isnt_overdue', 'hasnt_started', 'due', 'dtstart', 'priority'))
except:
tasks = find_calendar(caldav_conn, args).todos()
for attr in vtodo_txt_one + vtodo_txt_many: ## TODO: now we have _exact_ match on items in the the array attributes, and substring match on items that cannot be duplicated. Does that make sense? Probably not.
@@ -415,6 +424,10 @@ def todo_select(caldav_conn, args):
tasks = [x for x in tasks if hasattr(x.instance.vtodo, attr) and getattr(args, attr) in getattr(x.instance.vtodo, attr).value]
if getattr(args, 'no'+attr):
tasks = [x for x in tasks if not hasattr(x.instance.vtodo, attr)]
+ if args.overdue:
+ tasks = [x for x in tasks if hasattr(x.instance.vtodo, 'due') and _force_datetime(x.instance.vtodo.due.value, args) < _force_datetime(datetime.now(), args)]
+ if args.hide_future:
+ tasks = [x for x in tasks if not(hasattr(x.instance.vtodo, 'dtstart') and _force_datetime(x.instance.vtodo.dtstart.value, args) > _force_datetime(datetime.now(), args))]
if args.hide_parents or args.hide_children:
tasks_by_uid = {}
for task in tasks:
@@ -639,6 +652,8 @@ def main():
todo_parser.add_argument('--todo-uid')
todo_parser.add_argument('--hide-parents', help='Hide the parent if you need to work on children tasks first (parent task depends on children tasks to be done first)', action='store_true')
todo_parser.add_argument('--hide-children', help='Hide the parent if you need to work on children tasks first (parent task depends on children tasks to be done first)', action='store_true')
+ todo_parser.add_argument('--overdue', help='Only show overdue tasks', action='store_true')
+ todo_parser.add_argument('--hide-future', help='Hide events with future dtstart', action='store_true')
for attr in vtodo_txt_one + vtodo_txt_many:
todo_parser.add_argument('--'+attr, help="for filtering tasks")