every ===== *every* is a personal calendar tool, heavily inspired by the program [when](http://www.lightandmatter.com/when/when.html). it reads from a file containing a list of one-time or recurrent events, like this: ``` .warn 3d .stay 2d on 2019-12-20 20:00, friend's party (bring gifts) # short-term recurrent .warn 6H .stay 6H .urgent true every 10d from 2019-11-07 08:00 to 2020-01-27, prescribed medication .urgent false # holidays .warn 10d .stay 1d every 1y from _-12-24, クリスマスイブ! # birthdays .warn 5d .stay 3d every 1y from 1989-09-05, person a every 1y from 1992-12-18, person b ``` and prints out which of those events are upcoming (within their `.warn` period) or recent (within their `.stay` period): ``` Sat 2019 Dec 21 20:00 [ URGENT ] Today 18:00 prescribed medication [ normal ] Yesterday 20:00 friend's party (bring gifts) 2019 Dec 24 クリスマスイブ! ``` i wrote this program because when, useful as it is, can't handle recurrent events in the way i'd hoped it would, and in the process have also added a few other features that seemed useful, like an output mode for use in scripts. usage ----- ``` $ every --help Usage: ./dbg_every [-c CALENDAR_FILE] [-e TEXT_EDITOR] [COMMAND] every is a simple console-based event calendar -h --help print this help message and exit -v --version print the version of every in use and exit -c --calendar=FILE path to calendar file -e --editor=CMD text editor for editing calendars --line-term=CHAR line terminator for scripting output --col-delim=CHAR column delimiter for scripting output Commands c (default) print upcoming events in interactive console mode s print upcoming events in a format appropriate for scripting e open calendar with text editor ``` every has three basic commands: ### edit `every e` is a shortcut for opening the default calendar using `$EDITOR` (or the specified calendar using the specified command). the default calendar is `every/cal.every` under `$XDG_CONFIG_HOME` (which falls back to `$HOME/.config/` when not specified) if you use vim, a syntax file for the `.every` file format is available here: https://git.airen-no-jikken.icu/ageha/every.vim ### console `every c` prints out the upcoming events in a human-readable format, suitable for interactive use. this is the default command, so just `every` is equivalent. ### script `every s` prints the upcoming events in an easily-parseable format, for use in scripting. each line (by-default terminated with `\n`) represents one upcoming event, with fields (by default) delimited with `\t`. the fields are: | year | month | day | hour | minute | second | urgent | local | message | calendar format --------------- the calendar's grammar looks something like this: ``` CAL := CMD | ENTRY CMD := .local BOOL | .urgent BOOL | .warn INTERVAL | .stay INTERVAL BOOL := yes | true | on | no | false | off ENTRY := on DATE | on DATE , MESSAGE | every INTERVAL from DATE | every INTERVAL from DATE , MESSAGE | every INTERVAL from DATE to DATE | every INTERVAL from DATE to DATE , MESSAGE ``` a `DATE` represents a single point in time in the form `y-m-d H:M:S`, where trailing elements can be left off (so `2020-01-09 08:30` or even just `2020` are valid) and any element can be replaced with an underscore to substitute it with a default value (`_-12-09` == `2000-12-09`. `_-_-_ _:_:_` == `2000-01-01 00:00:00`) an `INTERVAL` represents a duration of time, and is made of one to six numbers, in any order, representing a number of years, months, days, hours, minutes and seconds. each element uses a single char subscript to indicate its type (`1y 3d 2m` is one year, two months, three days. `1H3M2S` is one hour, three minutes, two seconds). elements may not repeat (so `1y5H2d3y` is invalid) there are two types of calendar entries: `on` entries, for one-time events occurring on a given `DATE`, and `every` entries, for events that recur every `INTERVAL` amount of time. time intervals are calculated such that only the elements listed change. an `every 1y from _-03-12` event will *always* occur on march 12th. this means that the intervals `1y` and `365d` are not equivalent, because some years contain leap days, and it also means that `every 1y from 2008-02-29` will occur only during leap years a `MESSAGE` is an optional string describing the event that will be displayed when printing. if present, it must begin with a `,` and lasts until the end of the line each `CMD` changes settings which are applied to any following events. `.local` defaults to `true`, and dictates whether entries should be interpreted as local time, or else as UTC (which could be useful for e.g. people who change timezones often) `.urgent` defaults to `false`, and dictates whether entries should be displayed as "[ URGENT ]" in interactive output and have the urgent flag set in scripting output `.warn` defaults to `1d`, and is the warning period before an event actually occurs during which it should be considered active `.stay` defaults to `1d`, and is the amount of time an event should still be considered active after its occurrence note ---- this program requires a POSIX environment. it also makes use of the `timegm` function, which is a non-standard extension but commonly implemented. because of how `time.h` defines `struct tm`, and of how active events are calculated, every will not work correctly on architectures where `int` is smaller than 32 bits