From 9594bf42e14446a77d458624c07e3f856a0374d4 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Sat, 23 Sep 2017 17:13:44 -0400 Subject: Small cleanups/typos --- README.md | 20 +++++++++++++++++--- calendar-cli.py | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index da9aa10..31d15e6 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ not be up-to-date and may contain features not implemented yet. * --interactive: stop and query the user rather often * --caldav-url, --caldav-user, --caldav-pass: how to connect to the CalDAV server. Fits better into a configuration file. * --calendar-url: url to the calendar one wants to use. -* --config-file: use a specific configuration file (default: $HOME/.calendar-cli.conf) +* --config-file: use a specific configuration file (default: $HOME/.config/calendar.conf) * --config-section: use a specific section from the config file (i.e. to select a different caldav-server to connect to) * --icalendar: Write or read icalendar to/from stdout/stdin * --nocaldav: don't connect to a caldav server @@ -87,13 +87,27 @@ Configuration file is by default located in $HOME/.config/calendar.conf and shou The file may look like this: ```json -{ "default": - { "caldav_url": "http://foo.bar.example.com/caldav/", +{ "default": + { "caldav_url": "http://foo.bar.example.com/caldav/", "caldav_user": "luser", "caldav_pass": "insecure" } } ``` +A configuration with multiple sections may look like this: + +```json +{ "default": + { "caldav_url": "http://foo.bar.example.com/caldav/", + "caldav_user": "luser", + "caldav_pass": "insecure" + }, + { "caldav_url": "http://foo.baz.example.com/caldav/", + "caldav_user": "luser2", + "caldav_pass": "insecure2" + } +} +``` Optionally, in addition (or even instead) of "default", other "sections" can be created and selected through the --config-section option. The rationale is to allow configuration for multiple CalDAV-servers, or multiple calendars on the same CalDAV-server to remain in the same configuration file. Later versions will eventually be capable of copying events, or putting events into several calendars. diff --git a/calendar-cli.py b/calendar-cli.py index 7edd613..269140e 100755 --- a/calendar-cli.py +++ b/calendar-cli.py @@ -818,7 +818,7 @@ def main(): ## journal journal_parser = subparsers.add_parser('journal') - journal_subparsers = journal_parser.add_subparsers(title='tasks subcommand') + journal_subparsers = journal_parser.add_subparsers(title='journal subcommand') journal_add_parser = journal_subparsers.add_parser('add') journal_add_parser.add_argument('summaryline', nargs='+') journal_add_parser.set_defaults(func=journal_add) -- cgit v1.2.3 From a07318e9a83a9202ec0126b8b2935fdb8ac634c2 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Sat, 23 Sep 2017 17:16:16 -0400 Subject: typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 31d15e6..b7546d7 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ A configuration with multiple sections may look like this: "caldav_user": "luser", "caldav_pass": "insecure" }, - { "caldav_url": "http://foo.baz.example.com/caldav/", + "caldav_url": "http://foo.baz.example.com/caldav/", "caldav_user": "luser2", "caldav_pass": "insecure2" } -- cgit v1.2.3 From 8df06a8c825a1244788b301b7e20ed79707c8740 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Sun, 24 Sep 2017 01:34:40 -0400 Subject: typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b7546d7..d7b590d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Rationale GUIs and Web-UIs are nice for some purposes, but I really find the command line unbeatable when it comes to: -* Minor stuff that are repeated often. Writing something like "todo add make a calendar-cli system" or "cal add 'tomorrow 15:40+2h' doctor appointment" is just very much faster than navigating into some web calendar interface and add an item there. +* Minor stuff that are repeated often. Writing something like "todo add make a calendar-cli system" or "calendar add 'tomorrow 15:40+2h' doctor appointment" is just very much faster than navigating into some web calendar interface and add an item there. * Things that are outside the scope of the UI. Here is one of many tasks I'd like to do: "go through the work calendar, find all new calendar events that are outside office hours, check up with the personal calendar if there are potential conflicts, add some information at the personal calendar if appropriate", and vice versa - it has to be handled very manually if doing it through any normal calendar application as far as I know, but if having some simple CLI or python library I could easily make some interactive script that would help me doing the operation above. I've been looking a bit around, all I could find was cadaver and CalDAVClientLibrary. Both of those seems to be a bit shortcoming; they seem to miss the iCalendar parsing/generation, and there are things that simply cannot be done through those tools. -- cgit v1.2.3 From 9576705786d2d27c10669549c7081a4782ce090d Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Sun, 24 Sep 2017 01:35:42 -0400 Subject: Fix --whole-day capability --- calendar-cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/calendar-cli.py b/calendar-cli.py index 269140e..2d2ed3e 100755 --- a/calendar-cli.py +++ b/calendar-cli.py @@ -292,8 +292,8 @@ def calendar_add(caldav_conn, args): duration = int(event_spec[1][:-1]) dtstart = dateutil.parser.parse(event_spec[0]) dtend = dtstart + timedelta(days=duration) - event.add('dtstart', _date(dtstart.date)) - event.add('dtend', _date(dtend.date)) + event.add('dtstart', _date(dtstart.date())) + event.add('dtend', _date(dtend.date())) else: event.add('dtstart', dtstart) ## TODO: handle duration and end-time as options. default 3600s by now. -- cgit v1.2.3 From aca4fd0b53be96fe0f8b7cfdd99d2834a3f30814 Mon Sep 17 00:00:00 2001 From: Tobias Brox Date: Mon, 30 Oct 2017 14:42:03 +0100 Subject: the information in this file was rather obsoleted --- INSTALL.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index a916765..bc67ddf 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,11 +1,4 @@ Installing the calendar-cli =========================== -No packaging available yet; it's just to copy the python executable into the path, i.e. /usr/local/bin - -There are two dependencies; - -* icalendar library - I've used https://pypi.python.org/pypi/icalendar -* caldav library - I've used http://trac.calendarserver.org/wiki/CalDAVClientLibrary - but I'm strongly considering to switch to https://pypi.python.org/pypi/caldav - -All of those are under development and has to be installed manually. +"sudo ./setup.py install" should just work \ No newline at end of file -- cgit v1.2.3 From 172ab17c1c77936ba42b4ba91bf2ca9b8fd66a52 Mon Sep 17 00:00:00 2001 From: linxsorg Date: Sat, 20 Jan 2018 09:54:21 +0900 Subject: Changed strftime("%F") to strftime("%Y-%m-%d") to fit to Windows. --- calendar-cli.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/calendar-cli.py b/calendar-cli.py index 2d2ed3e..ec5784f 100755 --- a/calendar-cli.py +++ b/calendar-cli.py @@ -141,7 +141,7 @@ def _calendar_addics(caldav_conn, ics, uid, args): c = find_calendar(caldav_conn, args) c.add_event(ics) - + def calendar_addics(caldav_conn, args): """ Takes an ics from external source and puts it into the calendar. @@ -166,10 +166,10 @@ def calendar_addics(caldav_conn, args): ## since the icalendar library doesn't offer methods out of the ## hat for doing such kind of things entries = c.subcomponents - + ## Timezones should be duplicated into each ics, ref the RFC timezones = [x for x in entries if x.name == 'VTIMEZONE'] - + ## Make a mapping from UID to the other components uids = {} for x in entries: @@ -184,12 +184,12 @@ def calendar_addics(caldav_conn, args): def interactive_config(args, config, remaining_argv): import readline - + new_config = False section = 'default' backup = {} modified = False - + print("Welcome to the interactive calendar configuration mode") print("Warning - untested code ahead, raise issues at t-calendar-cli@tobixen.no") if not config or not hasattr(config, 'keys'): @@ -248,7 +248,7 @@ def interactive_config(args, config, remaining_argv): os.rename(args.config_file, "%s.%s.bak" % (args.config_file, int(time.time()))) with open(args.config_file, 'w') as outfile: json.dump(config, outfile, indent=4) - + if args.config_section == 'default' and section != 'default': config['default'] = config[section] @@ -260,7 +260,7 @@ def create_alarm(message, relative_timedelta): alarm.add('DESCRIPTION', message) alarm.add('TRIGGER', relative_timedelta, parameters={'VALUE':'DURATION'}) return alarm - + def calendar_add(caldav_conn, args): cal = Calendar() cal.add('prodid', '-//{author_short}//{product}//{language}'.format(author_short=__author_short__, product=__product__, language=args.language)) @@ -356,7 +356,7 @@ def journal_add(caldav_conn, args): _calendar_addics(caldav_conn, cal.to_ical(), uid, args) print("Added journal item with uid=%s" % uid) ## FULL STOP - should do some major refactoring before doing more work here! - + def todo_add(caldav_conn, args): ## TODO: copied from calendar_add, should probably be consolidated if args.icalendar or args.nocaldav: @@ -389,7 +389,7 @@ def todo_add(caldav_conn, args): rt.params['RELTYPE']=['CHILD'] rt.value = str(uid) t.save() - + for attr in vtodo_txt_one: if attr == 'summary': continue @@ -538,8 +538,8 @@ def todo_edit(caldav_conn, args): ## you may now access task.data to edit the raw ical, or ## task.instance.vtodo to edit a vobject instance task.save() - - + + def todo_postpone(caldav_conn, args): if args.nocaldav: raise ValueError("No caldav connection, aborting") @@ -553,7 +553,7 @@ def todo_postpone(caldav_conn, args): new_ts = dateutil.parser.parse(args.until) if not new_ts.time(): new_ts = _date(new_ts) - + tasks = todo_select(caldav_conn, args) for task in tasks: if new_ts: @@ -655,7 +655,7 @@ def todo_complete(caldav_conn, args): continue task.complete() - + def todo_delete(caldav_conn, args): if args.nocaldav: @@ -663,7 +663,7 @@ def todo_delete(caldav_conn, args): tasks = todo_select(caldav_conn, args) for task in tasks: task.delete() - + def config_section(config, section='default'): if section in config and 'inherits' in config[section]: ret = config_section(config, config[section]['inherits']) @@ -672,13 +672,13 @@ def config_section(config, section='default'): if section in config: ret.update(config[section]) return ret - + def main(): """ the main function does (almost) nothing but parsing command line parameters """ ## This boilerplate pattern is from - ## http://stackoverflow.com/questions/3609852 + ## http://stackoverflow.com/questions/3609852 ## We want defaults for the command line options to be fetched from the config file # Parse any conf_file specification @@ -771,8 +771,8 @@ def main(): for attr in vtodo_txt_one + vtodo_txt_many: todo_parser.add_argument('--no'+attr, help="for filtering tasks", action='store_true') - - #todo_parser.add_argument('--priority', ....) + + #todo_parser.add_argument('--priority', ....) #todo_parser.add_argument('--sort-by', ....) #todo_parser.add_argument('--due-before', ....) todo_subparsers = todo_parser.add_subparsers(title='tasks subcommand') @@ -789,12 +789,12 @@ def main(): help="specifies a time at which a reminder should be presented for this task, " \ "relative to the start time of the task (as a timestamp delta)") todo_add_parser.set_defaults(func=todo_add) - + todo_list_parser = todo_subparsers.add_parser('list') todo_list_parser.add_argument('--todo-template', help="Template for printing out the event", default="{dtstart}{dtstart_passed_mark} {due}{due_passed_mark} {summary}") todo_list_parser.add_argument('--default-due', help="Default number of days from a task is submitted until it's considered due", type=int, default=365) todo_list_parser.add_argument('--list-categories', help="Instead of listing the todo-items, list the unique categories used", action='store_true') - todo_list_parser.add_argument('--timestamp-format', help="strftime-style format string for the output timestamps", default="%F (%a)") + todo_list_parser.add_argument('--timestamp-format', help="strftime-style format string for the output timestamps", default="%Y-%m-%d (%a)") todo_list_parser.set_defaults(func=todo_list) todo_edit_parser = todo_subparsers.add_parser('edit') @@ -844,7 +844,7 @@ def main(): calendar_agenda_parser.add_argument('--agenda-mins', help="Fetch calendar for so many minutes", type=int) calendar_agenda_parser.add_argument('--agenda-days', help="Fetch calendar for so many days", type=int, default=7) calendar_agenda_parser.add_argument('--event-template', help="Template for printing out the event", default="{dstart} {summary}") - calendar_agenda_parser.add_argument('--timestamp-format', help="strftime-style format string for the output timestamps", default="%F %H:%M (%a)") + calendar_agenda_parser.add_argument('--timestamp-format', help="strftime-style format string for the output timestamps", default="%Y-%m-%d %H:%M (%a)") calendar_agenda_parser.set_defaults(func=calendar_agenda) calendar_delete_parser = calendar_subparsers.add_parser('delete') -- cgit v1.2.3