aboutsummaryrefslogtreecommitdiffstats
path: root/Readme.md
blob: c0034957ebd9f5e068a512739ce1639110260f51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
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-delim=CHAR  line delimiter 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 separated 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