pimutils / pimutils/khal

Day-by-day summary view

Open
#725 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

idea in progress type: enhancement
Dominant language
Python
Stars
3.1k
Forks
233
Avg merge
1h 44m
Merged PRs (30d)
1

Description

I coded myself a report showing a compact day-by-day view of my appointments, which I find useful for doing short to medium term planning. The code is a quick and dirty ripoff of the existing agenda report, and the holidays are hardcoded as the Italian ones. I find it utterly useful, and so here I share it. Feel free to add it to khal if you like it, consider it released under the public domain:

def do_summary(collection, dates=None, encoding='utf-8', show_all_days=False, full=False,
           week=False, bold_for_light_color=True, **kwargs):
    from click import echo
    term_width, _ = get_terminal_size()
    event_column = get_summary(collection, dates=dates, width=term_width,
                              show_all_days=show_all_days, full=full, week=week,

                              bold_for_light_color=bold_for_light_color, **kwargs)
    # XXX: Generate this as a unicode in the first place, rather than
    # casting it.
    echo('\n'.join(event_column))

def is_holiday(day):
    import dateutil.easter
    from datetime import date, timedelta
    if day.weekday() == 6:
        return True
    if (day.month, day.day) in (
            (1, 1), (1, 6), (4, 25),
            (5, 1), (6, 2), (8, 15),
            (11, 1), (12, 8), (12, 25),
            (23, 26)):
        return True

    easter = dateutil.easter.easter(day.year)
    if day == easter + timedelta(days=1):
        return True
    return False

def get_summary(collection, locale, dates=None, firstweekday=0, days=None, events=None, width=45,
               week=False, full=False, show_all_days=False, bold_for_light_color=True,):
    """returns a list of events scheduled for all days in daylist

    included are header "rows"
    :param collection:
    :type collection: khalendar.CalendarCollection
    :param dates: a list of all dates for which the events should be return,
                    including what should be printed as a header
    :type collection: list(str)
    :param show_all_days: True if all days must be shown, event without event
    :type show_all_days: Boolean
    :returns: a list to be printed as the agenda for the given days
    :rtype: list(str)

    """
    from datetime import date, timedelta
    from click import style, echo

    event_column = list()

    if days is None:
        days = 2

    if dates is None or len(dates) == 0:
        dates = [date.today()]
    else:
        try:
            dates = [
                aux.guessdatetimefstr([day], locale)[0].date()
                if not isinstance(day, date) else day
                for day in dates
            ]
        except InvalidDate as error:
            logging.fatal(error)
            sys.exit(1)

    if week:
        dates = [d - timedelta((d.weekday() - firstweekday) % 7)
                 for d in dates]
        days = 7

    if days is not None:
        daylist = [day + timedelta(days=one)
                   for one in range(days) for day in dates]
        daylist.sort()

    last_day = None
    for day in daylist:
        if last_day is None or day.month != last_day.month:
            event_column.append(style(day.strftime("%B"), bold=True))

        last_day = day
        events = sorted(collection.get_events_on(day))
        if is_holiday(day):
            prefix = style(day.strftime("%d*%a: "), bold=True)
        else:
            prefix = style(day.strftime("%d %a: "), bold=False)
        if not events:
            event_column.append(prefix)
            continue
        for event in events:
            lines = list()
            items = event.relative_to(day, full).splitlines()
            for item in items:
                lines += textwrap.wrap(item, width)
            lines = [colored(line, event.color, bold_for_light_color=bold_for_light_color) for line in lines]
            event_column.append(prefix + lines[0])
            prefix = " " * 8
            event_column += [prefix + line for line in lines[1:]]

    if event_column == []:
        event_column = [style('No events', bold=True)]
    return event_column

Here's an example output:

example-summary

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading khal's existing agenda report and the CLI entry point where reports are selected. Compare the proposed Python functions with that report and the supplied example output, then determine the integration and localization implications of the hardcoded Italian holidays. Done means the day-by-day summary is available as a khal report and produces the described output without relying on Italian-only holiday rules.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.