Skip to content

Commit

Permalink
config: Add output.week-start="sunday"|"monday" setting
Browse files Browse the repository at this point in the history
  • Loading branch information
dbarnett committed Sep 15, 2024
1 parent 45553ee commit 9910a04
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 30 deletions.
2 changes: 1 addition & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ v4.5.0
* Migrate data files like ~/.gcalcli_oauth into standard data file paths
(with fallback to migrate detected files into the new paths)
* Add support for $GCALCLI_CONFIG env var and deprecate --config-folder
* Add support for config.toml file with section "calendars"
* Add support for config.toml file with sections "calendars" and "output"

v4.4.0
* Fix lots of bugs by switching from deprecated oauth2client to
Expand Down
22 changes: 22 additions & 0 deletions data/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,33 @@
}
}
}
},
"OutputSection": {
"title": "Settings about gcalcli output (formatting, colors, etc)",
"type": "object",
"properties": {
"week-start": {
"title": "Weekday to treat as start of week",
"$ref": "#/$defs/WeekStart",
"default": "sunday"
}
}
},
"WeekStart": {
"title": "WeekStart",
"type": "string",
"enum": [
"sunday",
"monday"
]
}
},
"properties": {
"calendars": {
"$ref": "#/$defs/CalendarsSection"
},
"output": {
"$ref": "#/$defs/OutputSection"
}
}
}
15 changes: 10 additions & 5 deletions gcalcli/argparsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

import gcalcli

from . import env, utils
from . import config, env, utils
from .deprecations import DeprecatedStoreTrue, parser_allow_deprecated
from .details import DETAILS
from .printer import valid_color_name
Expand Down Expand Up @@ -235,11 +235,16 @@ def get_cal_query_parser():
cal_query_parser = argparse.ArgumentParser(add_help=False)
cal_query_parser.add_argument('start', type=str, nargs='?')
cal_query_parser.add_argument(
'--monday', action='store_true', dest='cal_monday', default=False,
help='Start the week on Monday')
'--monday',
action='store_const',
const=config.WeekStart.MONDAY,
dest='week_start',
# Note defaults to SUNDAY via config.OutputSection (not explicitly set
# here because that would override value from config).
help='Start the week on Monday')
cal_query_parser.add_argument(
'--noweekend', action='store_false', dest='cal_weekend',
default=True, help='Hide Saturday and Sunday')
'--noweekend', action='store_false', dest='cal_weekend',
default=True, help='Hide Saturday and Sunday')
return cal_query_parser


Expand Down
10 changes: 8 additions & 2 deletions gcalcli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,15 @@ def main():
tmp_argv if parsed_args.includeRc else argv
)

namespace_from_config = opts_from_config.to_argparse_namespace()
# Pull week_start aside and set it manually after parse_known_args.
# TODO: Figure out why week_start from opts_from_config getting through.
week_start = namespace_from_config.week_start
namespace_from_config.week_start = None
(parsed_args, unparsed) = parser.parse_known_args(
tmp_argv, namespace=opts_from_config.to_argparse_namespace()
)
tmp_argv, namespace=namespace_from_config)
if parsed_args.week_start is None:
parsed_args.week_start = week_start
if parsed_args.config_folder:
parsed_args.config_folder = parsed_args.config_folder.expanduser()

Expand Down
25 changes: 24 additions & 1 deletion gcalcli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
from collections import OrderedDict
from enum import Enum
import sys
from typing import Any, List, Mapping

Expand Down Expand Up @@ -34,6 +35,22 @@ class CalendarsSection(BaseModel):
)


class WeekStart(str, Enum):
SUNDAY = "sunday"
MONDAY = "monday"


class OutputSection(BaseModel):
model_config = ConfigDict(
title='Settings about gcalcli output (formatting, colors, etc)'
)

week_start: WeekStart = Field(
alias='week-start',
title='Weekday to treat as start of week',
default=WeekStart.SUNDAY)


class Config(BaseModel):
"""User configuration for gcalcli command-line tool.
Expand All @@ -46,14 +63,20 @@ class Config(BaseModel):
)

calendars: CalendarsSection = Field(default_factory=CalendarsSection)
output: OutputSection = Field(default_factory=OutputSection)

@classmethod
def from_toml(cls, config_file):
config = tomllib.load(config_file)
return cls(**config)

def to_argparse_namespace(self) -> argparse.Namespace:
return argparse.Namespace(**vars(self.calendars or {}))
kwargs = {}
if self.calendars:
kwargs.update(vars(self.calendars))
if self.output:
kwargs.update(vars(self.output))
return argparse.Namespace(**kwargs)

@classmethod
def json_schema(cls) -> Mapping[str, Any]:
Expand Down
42 changes: 21 additions & 21 deletions gcalcli/gcal.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

from . import actions, auth, env, ics, utils
from . import actions, auth, config, env, ics, utils
from ._types import Cache, CalendarListEntry, Event
from .actions import ACTIONS
from .conflicts import ShowConflicts
Expand Down Expand Up @@ -326,14 +326,16 @@ def _calendar_color(self, event, override_color=False):
else:
return 'default'

def _cal_monday(self, day_num):
"""Shift the day number if we're doing cal monday, or cal_weekend is
false, since that also means we're starting on day 1
"""
if self.options['cal_monday'] or not self.options['cal_weekend']:
day_num -= 1
if day_num < 0:
day_num = 6
def _cal_weekday_num(self, day: date | datetime) -> int:
"""Number of day of week for the given date.
Evaluates a date against week_start and cal_weekend options and returns
a day number starting from sunday=0 or monday=0."""
day_num = int(day.strftime('%w'))
if (self.options['week_start'] == config.WeekStart.MONDAY
or not self.options['cal_weekend']):
# Shift to count starting from monday (subtract 1, mod 7)
day_num = (day_num - 1 + 7) % 7
return day_num

def _event_time_in_range(self, e_time, r_start, r_end):
Expand Down Expand Up @@ -371,7 +373,7 @@ def _get_week_events(self, start_dt, end_dt, event_list):
now_in_week = False

for event in event_list:
event_daynum = self._cal_monday(int(event['s'].strftime('%w')))
event_daynum = self._cal_weekday_num(event['s'])
event_allday = is_all_day(event)

event_end_date = event['e']
Expand Down Expand Up @@ -436,10 +438,7 @@ def _get_week_events(self, start_dt, end_dt, event_list):
if event_end_date > end_dt:
end_daynum = 6
else:
end_daynum = \
self._cal_monday(
int(event_end_date.strftime('%w'))
)
end_daynum = self._cal_weekday_num(event_end_date)
if event_daynum > end_daynum:
event_daynum = 0
for day in range(event_daynum, end_daynum + 1):
Expand Down Expand Up @@ -520,7 +519,8 @@ def _GraphEvents(self, cmd, start_datetime, count, event_list):
days = 7 if self.options['cal_weekend'] else 5
# Get the localized day names... January 1, 2001 was a Monday
day_names = [date(2001, 1, i + 1).strftime('%A') for i in range(days)]
if not self.options['cal_monday'] or not self.options['cal_weekend']:
if (self.options['week_start'] != config.WeekStart.MONDAY
or not self.options['cal_weekend']):
day_names = day_names[6:] + day_names[:6]

def build_divider(left, center, right):
Expand Down Expand Up @@ -569,7 +569,7 @@ def build_divider(left, center, right):

# get date range objects for the first week
if cmd == 'calm':
day_num = self._cal_monday(int(start_datetime.strftime('%w')))
day_num = self._cal_weekday_num(start_datetime)
start_datetime = (start_datetime - timedelta(days=day_num))
start_week_datetime = start_datetime
end_week_datetime = (start_week_datetime + timedelta(days=7))
Expand Down Expand Up @@ -1281,7 +1281,7 @@ def CalQuery(self, cmd, start_text='', count=1):

# convert start date to the beginning of the week or month
if cmd == 'calw':
day_num = self._cal_monday(int(start.strftime('%w')))
day_num = self._cal_weekday_num(start)
start = (start - timedelta(days=day_num))
end = (start + timedelta(days=(count * 7)))
else: # cmd == 'calm':
Expand All @@ -1293,11 +1293,11 @@ def CalQuery(self, cmd, start_text='', count=1):
end_year += 1
end = start.replace(month=end_month, year=end_year)
days_in_month = (end - start).days
# TODO: Is this correct for --noweekend? Still uses % 7 below?
offset_days = int(start.strftime('%w'))
if self.options['cal_monday']:
offset_days -= 1
if offset_days < 0:
offset_days = 6
if self.options['week_start'] == config.WeekStart.MONDAY:
# Shift to count starting from monday (subtract 1, mod 7)
offset_days = (offset_days - 1 + 7) % 7
total_days = (days_in_month + offset_days)
count = int(total_days / 7)
if total_days % 7:
Expand Down

0 comments on commit 9910a04

Please sign in to comment.