#!/usr/bin/python
# ------------------------------------------
# Name: tasks
# Purpose: Handle command-line options.
#
# Author: Robin Siebler
# ------------------------------------------
"""
Usage: tasks.py priority [-a]
tasks.py delete <Task_ID>
tasks.py display <Task_ID>
tasks.py search <Search_String>
tasks.py modify <Task_ID> ([<Task>] | [-c] | [-p <Priority>] | [-d=<Due_Date> --time=<Time_Due>] | [-n <Note>] | [-t <Tags>])
tasks.py [<Task>] [-a] ([-p <Priority>] [-d=<Due_Date> --time=<Time_Due>] [-n <Note>] [-t <Tags>])
Commands:
delete <Task_ID> Delete a Task
display <Task_ID> Display the note for a Task. This allows you to add more info to a task
modify <Task_ID> The Task to modify followed by the updated information
priority Display the Tasks in priority order
search <Search-string> Search all the tasks for a given work or phrase. If the phrase contains
spaces, it must be enclosed in double quotes.
Arguments:
Task The task to add (Only 20 chars will be displayed)
Options:
-h --help Show this screen.
-a Display absolute dates
-c Mark a task as completed
-d <Due_Date> Date the task is due (Ex: M/D/YY, MM-DD-YYYY, MM.DD.YY)
-n <Note> A lengthier description of the task
-p <Priority> Priority - L, M, H (Low, Medium or High)
-t <Tags> Words you want to associate with this task
--time <Time_Due> Time the Task is due in the format h:mm AM/PM
Note: The Task, the Note and any Tags need to be in double quotes if they contain spaces.
"""
__author__ = 'Robin Siebler'
__date__ = '5/6/15'
import os
import platform
import sys
import time
try:
import arrow
except ImportError:
print 'The module "arrow" is required. Install it by running "pip install arrow".'
sys.exit(-5)
try:
import colorama
except ImportError:
print 'The module "colorama" is required. Install it by running "pip install colorama".'
sys.exit(-5)
try:
from docopt import docopt
except ImportError:
print 'The module "docopt" is required. Install it by running "pip install docopt".'
sys.exit(-5)
try:
from pyparsing import Regex, ParseException
except ImportError:
print 'The module "pyparsing" is required. Install it by running "pip install pyparsing".'
sys.exit(-5)
from task_functions import Functions
def validate_args(docopt_args):
"""Validate the user provided information."""
# validate priority
if docopt_args['-p']:
docopt_args['-p'] = docopt_args['-p'].upper()
if docopt_args['-p'] not in ['L', 'M', 'H']:
print '\nThe priority given is not valid.\n'
sys.exit(-4)
# validate date
if docopt_args['-d']:
pattern = Regex('^(1[0-2]|0?[1-9])(?P<Sep>(/|-|.))(3[01]|[12][0-9]|0?[1-9])(?P=Sep)(?:[0-9]{2})?[0-9]{2}$')
try:
pattern.parseString(docopt_args['-d'])
except ParseException:
print '\n' + docopt_args['-d'] + ' is not a valid date\n'
sys.exit(-3)
else:
# figure out what format the user provided...
if '/' in docopt_args['-d']:
date_sep = '/'
elif '-' in docopt_args['-d']:
date_sep = '-'
elif '.' in docopt_args['-d']:
date_sep = '.'
date = docopt_args['-d'].split(date_sep)
if len(date[0]) == 1:
month_format = 'M'
else:
month_format = 'MM'
if len(date[1]) == 1:
day_format = 'D'
else:
day_format = 'DD'
if len(date[2]) == 2:
year_format = 'YY'
else:
year_format = 'YYYY'
# get the time zone
# offset = time.strftime('%z', time.localtime()) <--- This doesn't work on windows
offset = ("-" if time.timezone > 0 else "+") + time.strftime("%H:%M", time.gmtime(abs(time.timezone)))
# parse the date
date_format = date_sep.join([month_format, day_format, year_format])
date_format = date_format + ' h:mm A Z'
if '--time' in docopt_args and docopt_args['--time']:
pattern = Regex('^ *(1[0-2]|[1-9]):[0-5][0-9] *(a|p|A|P)(m|M) *$')
try:
pattern.parseString(docopt_args['--time'])
except ParseException:
print '\nInvalid time format. Dropping Due Time.\n'
else:
# parse the date to make sure it is in the correct format:
dtime = docopt_args['--time'][:-2].strip()
period = docopt_args['--time'][-2:]
dtime = dtime + ' ' + period + ' ' + str(offset)
date = docopt_args['-d'] + ' ' + dtime
else:
date = docopt_args['-d'] + ' 11:59 PM ' + offset
date = arrow.get(date, date_format)
# validate due date occurs in the future
if date.date() < date.date().today():
print '\nWarning: The due date provided occurs in the past.\n'
docopt_args['-d'] = [date.format(date_format), date_format]
return docopt_args
def main(docopt_args):
docopt_args = validate_args(docopt_args)
tasks = Functions()
if platform.system() == 'Windows':
home_path = os.path.join(os.path.expandvars('%HOMEDRIVE%'), os.path.expandvars('%HOMEPATH%'))
task_file = os.path.join(home_path, 'tasks.tsk')
elif platform.system() == 'Darwin' or platform.system() == 'Linux':
task_file = os.path.join(os.path.expanduser('~'), 'tasks.tsk')
else:
print 'What OS are we on?'
sys.exit(-2)
task_file_exists = os.path.exists(task_file)
if not task_file_exists and docopt_args['<Task>'] is None:
print '\nThe file ' + task_file + ' does not exist. There are no tasks to display.\n'
sys.exit(-1)
elif task_file_exists:
tasks.load_tasks(task_file)
if docopt_args['modify']:
if docopt_args['<Task>']:
tasks.modify_task(docopt_args['<Task_ID>'], task_=docopt_args['<Task>'])
elif docopt_args['-c']:
tasks.modify_task(docopt_args['<Task_ID>'], completed=True)
elif docopt_args['-p']:
tasks.modify_task(docopt_args['<Task_ID>'], priority=docopt_args['-p'])
elif docopt_args['-d']:
tasks.modify_task(docopt_args['<Task_ID>'], due_date=docopt_args['-d'])
elif docopt_args['-n']:
tasks.modify_task(docopt_args['<Task_ID>'], note=docopt_args['-n'])
elif docopt_args['-t']:
tasks.modify_task(docopt_args['<Task_ID>'], tags=docopt_args['-t'])
elif docopt_args['--time']:
tasks.modify_task(docopt_args['<Task_ID>'], time=docopt_args['--time'])
elif docopt_args['<Task>']:
if docopt_args['-p']:
if docopt_args['-d']:
if docopt_args['-n']:
if docopt_args['-t']:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'],
due_date=docopt_args['-d'], note=docopt_args['-n'], tags=docopt_args['-t'])
else:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'],
due_date=docopt_args['-d'], note=docopt_args['-n'])
elif docopt_args['-t']:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'],
due_date=docopt_args['-d'], tags=docopt_args['-t'])
else:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'], due_date=docopt_args['-d'])
elif docopt_args['-n']:
if docopt_args['-t']:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'],
note=docopt_args['-n'], tags=docopt_args['-t'])
else:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'], note=docopt_args['-n'])
elif docopt_args['-t']:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'], tags=docopt_args['-t'])
else:
tasks.add_task(docopt_args['<Task>'], priority=docopt_args['-p'])
elif docopt_args['-d']:
tasks.add_task(docopt_args['<Task>'], due_date=docopt_args['-d'])
elif docopt_args['-n']:
tasks.add_task(docopt_args['<Task>'], note=docopt_args['-n'])
elif docopt_args['-t']:
tasks.add_task(docopt_args['<Task>'], tags=docopt_args['-t'])
else:
tasks.add_task(docopt_args['<Task>'])
elif docopt_args['delete']:
tasks.delete_task(docopt_args['<Task_ID>'])
elif docopt_args['display']:
tasks.show_task(docopt_args['<Task_ID>'])
elif docopt_args['priority']:
tasks.show_tasks_by_priority(date_format=docopt_args['-a'])
elif docopt_args['search']:
tasks.search_tasks(docopt_args['<Search_String>'])
elif docopt_args['-a']:
tasks.show_tasks(date_format=docopt_args['-a'])
else:
tasks.show_tasks()
tasks.save_tasks(task_file)
if __name__ == '__main__':
args = docopt(__doc__)
main(args)