예제 #1
0
def cmd_agenda(tl, args):
    """displays an agenda for a given date
    """
    with ColorRenderer() as cr:
        agenda_items = []
        # if not set, get agenda for today
        list_all = False
        if not args.date:
            args.date = datetime.datetime.now()
        elif args.date == "*":
            list_all = True
        else:
            args.date = to_date(args.date)
            if isinstance(args.date, basestring):
                print(u"Could not parse date argument '{date_str}'".format(date_str = args.date))
                quit(-1)
        for item in tl.list_items(lambda x: True if x.due_date else False):
            if is_same_day(args.date, item.due_date) or list_all:
                agenda_items.append(item)
        # default date used when no done date is specified
        na_date = datetime.datetime(1970, 1, 1)
        # sort filtered list by "due" date and whether they are already marked as "done" 
        agenda_items.sort(key=lambda x: (x.done, x.due_date) or (x.done, na_date))
        # group report/done items by date
        for keys, groups in groupby(agenda_items, 
            lambda x: ((x.due_date or na_date).year, (x.due_date or na_date).month, (x.due_date or na_date).day)
            ):
            # filter out default dates again
            if (na_date.year, na_date.month, na_date.day) == keys:
                print(u"No done date attached")
            else:
                print(u"Agenda for {0:d}-{1:02d}-{2:02d}:".format(*keys))
            for item in groups:
                print(" ", cr.render(item))
        suppress_if_quiet(u"{nr} todo items displayed.".format(nr = len(agenda_items)), args)
예제 #2
0
def cmd_archive(tl, args):
    """archives all non-current todo items and removes them from todo list
    
    moves all done / report items to other files (schema is specified in
    configuration) and removes them from the todo file.
    
    Required fields of :param:`args`:
    """
    # base directory of todo file
    base_dir = os.path.dirname(conf.todo_file)

    # get list of done and report items
    report_list = list(tl.list_items(lambda x: x.done or x.is_report))
    # default date used when no done date is specified
    na_date = datetime.datetime(1970, 1, 1)
    # sort filtered list by "done" date
    report_list.sort(key=lambda x: x.done_date or na_date, reverse=True)

    # for mapping items to file names
    file_map = collections.defaultdict(list)

    for item in report_list:
        item_date = item.done_date or na_date
        if is_same_day(item_date, na_date):
            dst_fn = conf.archive_unsorted_filename
        else:
            dst_fn = os.path.join(
                base_dir, item_date.strftime(conf.archive_filename_scheme))

        # if not existing, create it
        if not os.path.exists(os.path.dirname(dst_fn)):
            os.makedirs(os.path.dirname(dst_fn))
        # add to file map
        file_map[dst_fn].append(item)

    nr_archived = 0
    # now we append the items to the right file
    for dst_fn in file_map:
        nr_archived += len(file_map[dst_fn])
        # open files in append mode
        with codecs.open(dst_fn, "a", "utf-8") as fp:
            for item in file_map[dst_fn]:
                # and write them
                fp.write(item.text + "\n")
                # and remove the item from todo list
                tl.remove_item(item)

    suppress_if_quiet(
        u"Successfully archived {nr} todo items.".format(nr=nr_archived), args)
예제 #3
0
def cmd_archive(tl, args):
    """archives all non-current todo items and removes them from todo list
    
    moves all done / report items to other files (schema is specified in
    configuration) and removes them from the todo file.
    
    Required fields of :param:`args`:
    """
    # base directory of todo file
    base_dir = os.path.dirname(conf.todo_file)
    
    # get list of done and report items
    report_list = list(tl.list_items(lambda x: x.done or x.is_report))
    # default date used when no done date is specified
    na_date = datetime.datetime(1970, 1, 1)
    # sort filtered list by "done" date 
    report_list.sort(key=lambda x: x.done_date or na_date, reverse=True)
    
    # for mapping items to file names
    file_map = collections.defaultdict(list)
    
    for item in report_list:
        item_date = item.done_date or na_date
        if is_same_day(item_date, na_date):
            dst_fn = conf.archive_unsorted_filename
        else:
            dst_fn = os.path.join(base_dir, item_date.strftime(conf.archive_filename_scheme))
        
        # if not existing, create it
        if not os.path.exists(os.path.dirname(dst_fn)):
            os.makedirs(os.path.dirname(dst_fn))
        # add to file map
        file_map[dst_fn].append(item)
    
    nr_archived = 0
    # now we append the items to the right file
    for dst_fn in file_map:
        nr_archived += len(file_map[dst_fn])
        # open files in append mode
        with codecs.open(dst_fn, "a", "utf-8") as fp:
            for item in file_map[dst_fn]:
                # and write them
                fp.write(item.text + "\n")
                # and remove the item from todo list
                tl.remove_item(item)
    
    suppress_if_quiet(u"Successfully archived {nr} todo items.".format(nr = nr_archived), args)
예제 #4
0
def cmd_agenda(tl, args):
    """displays an agenda for a given date
    
    Required fields of :param:`args`:
    * date: either a date or a string like 'tomorrow' or '*', default 'today'
    """
    with ColorRenderer() as cr:
        agenda_items = []
        # if not set, get agenda for today
        list_all = False
        if not args.date:
            args.date = datetime.datetime.now()
        elif args.date == "*":
            list_all = True
        else:
            args.date = to_date(args.date)
            if isinstance(args.date, basestring):
                print(u"Could not parse date argument '{date_str}'".format(
                    date_str=args.date))
                quit(-1)
        for item in tl.list_items(lambda x: True if x.due_date else False):
            if is_same_day(args.date, item.due_date) or list_all:
                agenda_items.append(item)
        # default date used when no done date is specified
        na_date = datetime.datetime(1970, 1, 1)
        # sort filtered list by "due" date and whether they are already marked as "done"
        agenda_items.sort(
            key=lambda x: (x.done, x.due_date) or (x.done, na_date))
        # group report/done items by date
        for keys, groups in groupby(
                agenda_items, lambda x:
            ((x.due_date or na_date).year, (x.due_date or na_date).month,
             (x.due_date or na_date).day)):
            # filter out default dates again
            if (na_date.year, na_date.month, na_date.day) == keys:
                print(u"No done date attached")
            else:
                print(u"Agenda for {0:d}-{1:02d}-{2:02d}:".format(*keys))
            for item in groups:
                print(" ", cr.render(item))
        suppress_if_quiet(
            u"{nr} todo items displayed.".format(nr=len(agenda_items)), args)
예제 #5
0
def cmd_report(tl, args):
    """shows a daily report of all done and report items
    
    :description: This command lists all done and report items for a given date
        or date range. If no arguments are given, the items of the last 7 days are
        displayed. 
    
    Required fields of :param:`args`:
    * from_date: either a date or a string like 'tomorrow' or '*'
    * to_date: either a date or a string like 'tomorrow'
    """
    with ColorRenderer() as cr:
        # default date used when no done date is specified
        na_date = datetime.datetime(1970, 1, 1, 0, 0, 0, 0)
        # today
        now = datetime.datetime.now().replace(hour=0,
                                              minute=0,
                                              second=0,
                                              microsecond=0)
        # check from and to date, make them datetime or None
        # what mode are we in?
        mode = None
        if args.from_date in ("*", "all"):
            mode, args.from_date, args.to_date = "ALL", na_date, now
        else:
            args.from_date = to_date(args.from_date)
            args.to_date = to_date(args.to_date)
            if isinstance(args.from_date, datetime.datetime):
                args.from_date = args.from_date.replace(hour=0,
                                                        minute=0,
                                                        second=0,
                                                        microsecond=0)
            else:
                logger.debug(
                    u"Cannot parse {date}".format(date=args.from_date))
                args.from_date = None
            if isinstance(args.to_date, datetime.datetime):
                args.to_date = args.to_date.replace(hour=0,
                                                    minute=0,
                                                    second=0,
                                                    microsecond=0)
            else:
                logger.debug(u"Cannot parse {date}".format(date=args.to_date))
                args.to_date = None

        if args.from_date and args.to_date and not mode:
            mode = "RANGE"
        elif args.from_date and not args.to_date:
            mode, args.to_date = "DAY", args.from_date
        elif not mode:
            # last 7 days
            mode, args.from_date, args.to_date = "LASTWEEK", now - datetime.timedelta(
                days=7), now

        # swap dates, if necessary
        if args.from_date > args.to_date:
            args.from_date, args.to_date = args.to_date, args.from_date
        # set end date to end of day
        args.to_date = args.to_date.replace(hour=23, minute=59, second=59)

        logger.debug(u"Report mode {0}: from {1} to {2}".format(
            mode, args.from_date, args.to_date))

        # get list of done and report items from current todo list
        report_list = list(tl.list_items(lambda x: (x.done or x.is_report)))

        # get list of done and report items from un-dated archive file
        root_dir = os.path.dirname(conf.todo_file)
        unsorted_fn = os.path.join(root_dir, conf.archive_unsorted_filename)
        if os.path.exists(unsorted_fn):
            res = TodoList(unsorted_fn)
            report_list.extend(res.todolist)

        # get all archive file names in list
        file_pattern = re_replace_archive_vars.sub(
            "*", conf.archive_filename_scheme)
        file_list = glob.glob(os.path.join(root_dir, file_pattern))

        # regex for finding all replaced parts in archive filename scheme
        re_find_date_str = re_replace_archive_vars.sub(
            "(.+)", conf.archive_filename_scheme).replace("\\", "\\\\")
        re_find_date = re.compile(re_find_date_str, re.UNICODE)
        # loop through all files and see, whether they match the given date range
        for fn in file_list:
            # get all replaced values in filename
            parts = re_find_date.findall(fn)[0]
            # get the variables responsible for this substitution (e.archived_items. "%Y", "%m", ...)
            tvars = re_replace_archive_vars.findall(
                conf.archive_filename_scheme)
            # create mapping, removing duplicates
            mapping = dict(zip(tvars, parts))
            # create date from mapping
            tdate = datetime.datetime.strptime(" ".join(mapping.values()),
                                               " ".join(mapping))

            # if filename matches date range
            if args.from_date <= tdate <= args.to_date:
                # load todo list
                res = TodoList(fn)
                # get items directly if they are done or report items
                archived_items = [
                    item for item in res.todolist
                    if item.done or item.is_report
                ]
                for item in archived_items:
                    # replace id with (A) to mark it as archived
                    item.replace_or_add_prop(conf.ID, "(A)")
                # append it to candidates
                report_list.extend(archived_items)

        # sort filtered list by "done" date
        report_list.sort(key=lambda x: x.done_date or na_date)

        nr = 0
        # group report/done items by date
        for keys, groups in groupby(
                report_list, lambda x:
            ((x.done_date or na_date).year, (x.done_date or na_date).month,
             (x.done_date or na_date).day)):
            # we are looking at that date right now
            temp_date = datetime.datetime(year=keys[0],
                                          month=keys[1],
                                          day=keys[2])
            # that date does not match the requested date range: skip
            if not args.from_date <= temp_date <= args.to_date:
                continue
            # filter out default dates again
            if is_same_day(na_date, temp_date):
                print(u"Report for unknown date:")
            else:
                print(u"Report for {date}:".format(
                    date=temp_date.strftime("%A, %Y-%m-%d")))
            # print the items, finally
            for item in groups:
                print(" ", cr.render(item))
                nr += 1

        suppress_if_quiet(u"{nr} todo items displayed.".format(nr=nr), args)
예제 #6
0
def cmd_report(tl, args):
    """shows a daily report of all done and report items
    """
    with ColorRenderer() as cr:
        # default date used when no done date is specified
        na_date = datetime.datetime(1970, 1, 1, 0, 0, 0, 0)
        # today
        now = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
        # check from and to date, make them datetime or None
        # what mode are we in?
        mode = None
        if args.from_date in ("*", "all"):
            mode, args.from_date, args.to_date = "ALL", na_date, now
        else:
            args.from_date = to_date(args.from_date)
            args.to_date = to_date(args.to_date)
            if isinstance(args.from_date, datetime.datetime):
                args.from_date = args.from_date.replace(hour=0, minute=0, second=0, microsecond=0)
            else:
                logger.debug(u"Cannot parse {date}".format(date = args.from_date))
                args.from_date = None
            if isinstance(args.to_date, datetime.datetime):
                args.to_date = args.to_date.replace(hour=0, minute=0, second=0, microsecond=0)
            else:
                logger.debug(u"Cannot parse {date}".format(date = args.to_date))
                args.to_date = None
        
        if args.from_date and args.to_date and not mode:
            mode = "RANGE"
        elif args.from_date and not args.to_date:
            mode, args.to_date = "DAY", args.from_date
        elif not mode:
            # last 7 days
            mode, args.from_date, args.to_date = "LASTWEEK", now - datetime.timedelta(days=7), now

        # swap dates, if necessary
        if args.from_date > args.to_date:
            args.from_date, args.to_date = args.to_date, args.from_date
        # set end date to end of day
        args.to_date = args.to_date.replace(hour=23, minute=59, second=59)
        
        logger.debug(u"Report mode {0}: from {1} to {2}".format(mode, args.from_date, args.to_date))
        
        # get list of done and report items from current todo list
        report_list = list(tl.list_items(lambda x: (x.done or x.is_report)))
        
        # get list of done and report items from un-dated archive file
        root_dir = os.path.dirname(conf.todo_file)
        unsorted_fn = os.path.join(root_dir, conf.archive_unsorted_filename)
        if os.path.exists(unsorted_fn):
            res = TodoList(unsorted_fn)
            report_list.extend(res.todolist)
        
        # get all archive file names in list
        file_pattern = re_replace_archive_vars.sub("*", conf.archive_filename_scheme)
        file_list = glob.glob(os.path.join(root_dir, file_pattern))

        # regex for finding all replaced parts in archive filename scheme
        re_find_date_str = re_replace_archive_vars.sub("(.+)", conf.archive_filename_scheme).replace("\\", "\\\\")
        re_find_date = re.compile(re_find_date_str, re.UNICODE)
        # loop through all files and see, whether they match the given date range
        for fn in file_list:
            # get all replaced values in filename
            parts = re_find_date.findall(fn)[0]
            # get the variables responsible for this substitution (e.archived_items. "%Y", "%m", ...)
            tvars = re_replace_archive_vars.findall(conf.archive_filename_scheme)
            # create mapping, removing duplicates
            mapping = dict(zip(tvars, parts))
            # create date from mapping
            tdate = datetime.datetime.strptime(" ".join(mapping.values()), " ".join(mapping))
            
            # if filename matches date range
            if args.from_date <= tdate <= args.to_date:
                # load todo list
                res = TodoList(fn)
                # get items directly if they are done or report items
                archived_items = [item for item in res.todolist if item.done or item.is_report]
                for item in archived_items:
                    # replace id with (A) to mark it as archived
                    item.replace_or_add_prop(conf.ID, "(A)")
                # append it to candidates
                report_list.extend(archived_items)
        
        # sort filtered list by "done" date 
        report_list.sort(key=lambda x: x.done_date or na_date)
        
        nr = 0
        # group report/done items by date
        for keys, groups in groupby(report_list, 
            lambda x: ((x.done_date or na_date).year, (x.done_date or na_date).month, (x.done_date or na_date).day)
            ):
            # we are looking at that date right now
            temp_date = datetime.datetime(year=keys[0], month=keys[1], day=keys[2])
            # that date does not match the requested date range: skip
            if not args.from_date <= temp_date <= args.to_date:
                continue
            # filter out default dates again
            if is_same_day(na_date, temp_date):
                print(u"Report for unknown date:")
            else:
                print(u"Report for {date}:".format(date = temp_date.strftime("%A, %Y-%m-%d")))
            # print the items, finally
            for item in groups:
                print(" ", cr.render(item))
                nr += 1
        
        suppress_if_quiet(u"{nr} todo items displayed.".format(nr = nr), args)