commit 2b4be20507fee93fc165a550cd0cb8f81dcad05d
parent 3a33fa3c7921c69efbc9beaaa922452ba2eaf271
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Mon, 15 May 2023 18:31:12 +0200
Updated .gitignore, README formatting
Diffstat:
M | .gitignore | | | 2 | +- |
M | README.md | | | 60 | +++++++++++++++++++++++++++++++++--------------------------- |
D | sdep-0.2/LICENSE | | | 21 | --------------------- |
D | sdep-0.2/Makefile | | | 61 | ------------------------------------------------------------- |
D | sdep-0.2/sdep.1 | | | 94 | ------------------------------------------------------------------------------- |
D | sdep-0.2/sdep.c | | | 277 | ------------------------------------------------------------------------------- |
6 files changed, 34 insertions(+), 481 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,2 +1,2 @@
sdep
-sdep-*.tar.gz
+sdep-*
diff --git a/README.md b/README.md
@@ -1,26 +1,30 @@
# sdep
+
A simple "date+event" line parser.
-sdep follows the UNIX philosphy (do one thing well, use stdin and stdout) and
-is heavily inspired by [suckless](https://suckless.org) utilities such as
-[dmenu](https://tools.suckless.org/dmenu/).
+sdep follows the UNIX philosphy (do one thing well, use stdin and stdout)
+and is heavily inspired by [suckless](https://suckless.org) utilities
+such as [dmenu](https://tools.suckless.org/dmenu/).
-You can wrap it around shell scripts to turn it into a no-nonsense calendar
-system.
+You can wrap it around shell scripts to turn it into a no-nonsense
+calendar system.
## Description
-sdep reads lines of the form `date text` from stdin and writes to stdout those
-lines such that `date` is between the two dates specified with the `-f` and
-`-t` options, both of which default to the current minute.
+sdep reads lines of the form `date text` from stdin and writes to stdout
+those lines such that `date` is between the two dates specified with the
+`-f` and `-t` options, both of which default to the current minute.
-The format for `date` can be specified with the same syntax as for date(1).
-The dates should correspond to a unique minute in time.
+The format for `date` can be specified with the same syntax as for
+date(1). The dates should correspond to a unique minute in time.
## Installation
-Edit the Makefile to match your local configuration and type `make install`.
+
+Edit the Makefile to match your local configuration and type `make
+install`.
## Examples
+
If `events.txt` contains lines formatted as `date text` then
```
@@ -39,25 +43,26 @@ will print all the lines whose date is in the past, while
sdep -t -w "%A" <events.txt
```
-will print all lines whose date is in the future, showing only the day of the
-week and the text.
+will print all lines whose date is in the future, showing only the day
+of the week and the text.
```
sdep -f "1999-01-01 00:00" -t "1999-12-31 23:59" -w "" <events.txt
```
-will show only the `text` of all lines with a date in 1999. You can specify a
-different format for the dates, for example
+will show only the `text` of all lines with a date in 1999. You can
+specify a different format for the dates, for example
```
sdep +"%m/%d/%Y %I:%M%p" -t "12/31/2020 11:59pm" -w "" <events.txt
```
will match all dates from December 31st, 2020, one minute before midnight
-(included). Note: this only works if your locale has an am/pm format, see
-date(1).
+(included). Note: this only works if your locale has an am/pm format,
+see date(1).
## A stupidly simple calendar app
+
If you keep your events and reminders in a simple plain text file (say
events.txt), you can run
@@ -65,12 +70,12 @@ events.txt), you can run
sdep -w "" -s "" | while read text; do notify-send "$text"; done < events.txt
```
-every minute, for example using cron(8), to get a notification every time
-an events is happens.
+every minute, for example using cron(8), to get a notification every
+time an events is happens.
You can use `sdep -f -t < events.txt` to list all your events, or
-`sdep -t < events.txt` to list only the future ones. You can specify any date
-range. Running
+`sdep -t < events.txt`
+to list only the future ones. You can specify any date range. Running
```
temp = $(mktemp)
@@ -80,18 +85,19 @@ mv "$temp" events.txt
will remove all old events from your file.
-You can edit your events using any text editor and you can keep them synced
-between multiple devices using something like
+You can edit your events using any text editor and you can
+keep them synced between multiple devices using something like
[rsync](https://rsync.samba.org/).
## Scripts
+
The `scripts` folder contains the few scripts that I use. They are
basically just a more elaborate version of the calendar system described
above, with support for recurring events (e.g. weekly, daily). You
can install them with `sudo SD=/path/to/scripts/folder make scripts`,
-where `SD` specifies the path where the directory where you want your sdep
-files to be saved; for example it can be `/home/username/.sdep`.
+where `SD` specifies the path where the directory where you want your
+sdep files to be saved; for example it can be `/home/username/.sdep`.
For example check that the folder SDEPDATA in Makefile suits you.
-Most of the scripts rely on the `-d` option of the GNU date utility, so you
-should change that too if you are on a BSD system or on MacOS.
+Most of the scripts rely on the `-d` option of the GNU date utility,
+so you should change that too if you are on a BSD system or on MacOS.
diff --git a/sdep-0.2/LICENSE b/sdep-0.2/LICENSE
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2021-2023 Sebastiano Tronto
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/sdep-0.2/Makefile b/sdep-0.2/Makefile
@@ -1,61 +0,0 @@
-# See LICENSE file for copyright and license details.
-
-VERSION = 0.2
-
-PREFIX = /usr/local
-MANPREFIX = ${PREFIX}/share/man
-SCRIPTS = sdep-add sdep-checknow sdep-checkpast sdep-clear sdep-edit sdep-list
-
-CPPFLAGS = -D_XOPEN_SOURCE=700 -DVERSION=\"${VERSION}\"
-CFLAGS = -pedantic -Wall -Os ${CPPFLAGS}
-DBGFLAGS = -pedantic -Wall -Wextra \
- -fsanitize=address -fsanitize=undefined ${CPPFLAGS}
-
-CC = cc
-
-
-all: options sdep
-
-options:
- @echo sdep build options:
- @echo "CFLAGS = ${CFLAGS}"
- @echo "CC = ${CC}"
-
-sdep:
- ${CC} ${CFLAGS} -o sdep sdep.c
-
-debug:
- ${CC} ${CFLAGS} -o sdep sdep.c
-
-clean:
- rm -rf sdep sdep-${VERSION}.tar.gz
-
-dist: clean
- mkdir -p sdep-${VERSION}
- cp -R LICENSE Makefile README sdep.1 sdep.c sdep-${VERSION}
- tar -cf sdep-${VERSION}.tar sdep-${VERSION}
- gzip sdep-${VERSION}.tar
- rm -rf sdep-${VERSION}
-
-install: all
- mkdir -p ${DESTDIR}${PREFIX}/bin
- cp -f sdep ${DESTDIR}${PREFIX}/bin/sdep
- chmod 755 ${DESTDIR}${PREFIX}/bin/sdep
- mkdir -p ${DESTDIR}${MANPREFIX}/man1
- sed "s/VERSION/${VERSION}/g" < sdep.1 \
- > ${DESTDIR}${MANPREFIX}/man1/sdep.1
- chmod 644 ${DESTDIR}${MANPREFIX}/man1/sdep.1
-
-scripts:
- for s in ${SCRIPTS}; do\
- sed "s|SDEPDATA|${SD}|g" < scripts/$$s > \
- ${DESTDIR}${PREFIX}/bin/$$s ; \
- chmod 755 ${DESTDIR}${PREFIX}/bin/$$s ;\
- done
-
-uninstall:
- rm -rf ${DESTDIR}${PREFIX}/bin/sdep ${DESTDIR}${MANPREFIX}/man1/sdep.1
- for s in ${SCRIPTS}; do rm -rf ${DESTDIR}${PREFIX}/bin/$$s; done
-
-.PHONY: all options debug clean dist install scripts uninstall
-
diff --git a/sdep-0.2/sdep.1 b/sdep-0.2/sdep.1
@@ -1,94 +0,0 @@
-.Dd May 13, 2021
-.Dt SDEP 1
-.Os
-.Sh NAME
-.Nm sdep
-.Nd a simple "date+event" line parser
-
-.Sh SYNOPSIS
-.Nm
-.Op Fl dv
-.Op Ar +format
-.Op Fl f Op Ar date
-.Op Fl t Op Ar date
-.Op Fl w Ar format
-.Op Fl s Ar string
-
-.Sh DESCRIPTION
-.Nm
-reads lines of the form
-
-.Dl Ar "date text"
-
-from stdin and writes to stdout those lines such that
-.Ar date
-is between the dates specified by the
-.Fl f
-and
-.Fl t
-options, both defaulting to the current minute.
-The dates should correspond to a unique minute in time. The format for
-.Ar date
-can be specified with the same syntax as for
-.Xr date 1 .
-
-The options are as follows:
-.Bl -tag -width Ds
-.It Fl d
-print the default date format and exit.
-.It Fl f Op Ar date
-initial date for the range (default: current minute). If
-.Ar date
-is not specified there will be no lower bound for the dates.
-.It Fl s Ar string
-change the string that separates the date from the text in the output
-lines (deafult: "\t").
-.It Fl t Op Ar date
-final date for the range (default: current minute). If
-.Ar date
-is not specified then there will be no upper bound for the dates.
-.It Fl v
-print version information and exit.
-.It Fl w Ar format
-change the format in which the date is written in the output lines.
-
-.Sh EXAMPLES
-If
-.Ar events.txt
-contains lines formatted as
-.Ar "date text"
-then
-
-.Dl sdep -f <events.txt
-
-will print all the lines whose date is in the past, while
-
-.Dl sdep -t -w "%A" <events.txt
-
-will print all lines whose date is in the future, showing only the day of the
-week and the text.
-
-.Dl sdep -f "1999-01-01 00:00" -t "1999-12-31 23:59" -w "" <events.txt
-
-will show only the
-.Ar text
-of all lines with a date in 1999. You can specify a different format for the
-dates, for example
-
-.Dl sdep +"%m/%d/%Y %I:%M%p" -t "12/31/2020 11:59pm" -w "" <events.txt
-
-will match all dates from December 31st, 2020, one minute before midnight
-(included). Note: this only works if your locale has an am/pm format, see
-.Xr date 1 .
-
-.Sh AUTHORS
-.An Sebastiano Tronto Aq Mt sebastiano.tronto@gmail.com
-
-.Sh SOURCE CODE
-Source code is available at
-.Lk https://github.com/sebastianotronto/sdep
-
-.Sh SEE ALSO
-.Xr date 1 ,
-.Xr strftime 3 ,
-.Xr strptime 3
diff --git a/sdep-0.2/sdep.c b/sdep-0.2/sdep.c
@@ -1,277 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-/*
- * Maximum number of characters in a line. The rest will be truncated.
- * Change this if you need very long lines.
- */
-#define MAXLEN 10000
-
-/*
- * Default date format. Anything that strftime(3) understands works, but
- * it should determine a date completely up to the minute.
- */
-static char *default_format = "%Y-%m-%d %H:%M";
-
-
-typedef struct Event Event;
-typedef struct EventList EventList;
-typedef struct EventNode EventNode;
-typedef struct Options Options;
-
-struct Event{
- struct tm time;
- char *text;
-};
-
-struct EventList {
- EventNode *first;
- EventNode *last;
- int count;
-};
-
-struct EventNode {
- Event ev;
- EventNode *next;
-};
-
-struct Options {
- struct tm from;
- struct tm to;
- char *format_in;
- char *format_out;
- char *separator;
-};
-
-static void add_event(struct tm, char *, EventList *);
-static int compare_tm(const void *, const void *);
-static int compare_event(const void *, const void *);
-static Options default_op(void);
-static int events_in_range(EventList *, Options, Event *);
-static char *format_line(Event, Options, char *);
-static int is_space(char);
-static void read_input(Options, EventList *);
-static Options read_op(int, char *[]);
-static void str_copy(char *, char *, int);
-static char *str_trim(char *);
-static void write_output(Options, Event *, int);
-
-
-static void
-add_event(struct tm t, char *text, EventList *evlist)
-{
- size_t l = strlen(text)+1;
- EventNode *next = malloc(sizeof(EventNode));
-
- next->ev.time = t;
- next->ev.text = malloc(l);
- str_copy(next->ev.text, text, l);
- next->ev.text = str_trim(next->ev.text);
- next->next = NULL;
-
- if (++evlist->count == 1) {
- evlist->first = next;
- evlist->last = next;
- } else {
- evlist->last->next = next;
- evlist->last = next;
- }
-}
-
-static int
-compare_tm(const void *v1, const void *v2)
-{
- const struct tm *t1 = v1;
- const struct tm *t2 = v2;
-
- if (t1->tm_year != t2->tm_year)
- return t1->tm_year - t2->tm_year;
- if (t1->tm_mon != t2->tm_mon)
- return t1->tm_mon - t2->tm_mon;
- if (t1->tm_mday != t2->tm_mday)
- return t1->tm_mday - t2->tm_mday;
- if (t1->tm_hour != t2->tm_hour)
- return t1->tm_hour - t2->tm_hour;
- return t1->tm_min - t2->tm_min;
-}
-
-static int
-compare_event(const void *v1, const void *v2)
-{
- const Event *ev1 = v1;
- const Event *ev2 = v2;
-
- return compare_tm(&ev1->time, &ev2->time);
-}
-
-static Options
-default_op(void)
-{
- Options op;
- time_t t_now = time(NULL);
- struct tm *now = localtime(&t_now);
-
- op.format_in = malloc(MAXLEN);
- op.format_out = malloc(MAXLEN);
- op.separator = malloc(MAXLEN);
- strcpy(op.format_in, default_format);
- strcpy(op.format_out, default_format);
- strcpy(op.separator, "\t");
- op.from = *now;
- op.to = *now;
-
- return op;
-}
-
-/*
- * Saves the events in ev[] that happen between op->from and op->to in sel[]
- * sorted by date and returns their number.
- */
-static int
-events_in_range(EventList *evlist, Options op, Event *sel)
-{
- EventNode *i;
- int n = 0;
-
- for (i = evlist->first; i != NULL; i = i->next)
- if (compare_tm(&i->ev.time, &op.from) >= 0 &&
- compare_tm(&i->ev.time, &op.to) <= 0)
- sel[n++] = i->ev;
-
- qsort(sel, n, sizeof(Event), compare_event);
-
- return n;
-}
-
-static char *
-format_line(Event ev, Options op, char *out)
-{
- size_t l;
-
- strftime(out, MAXLEN, op.format_out, &ev.time);
- l = strlen(out);
-
- str_copy(out+l, op.separator, MAXLEN - l);
- l = strlen(out);
-
- str_copy(out+l, ev.text, MAXLEN - l);
-
- return out;
-}
-
-static int
-is_space(char c)
-{
- return c == ' ' || c == '\t';
-}
-
-static void
-read_input(Options op, EventList *evlist)
-{
- struct tm t;
- char line[MAXLEN], *text_ptr;
-
- while (fgets(line, MAXLEN, stdin) != NULL)
- if ((text_ptr = strptime(line, op.format_in, &t)) != NULL)
- add_event(t, text_ptr, evlist);
-}
-
-static Options
-read_op(int argc, char *argv[])
-{
- Options op = default_op();
- int i;
-
- /* Check for format specification.
- * This changes the way other options are read */
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '+') {
- str_copy(op.format_in, &argv[i][1], MAXLEN);
- str_copy(op.format_out, &argv[i][1], MAXLEN);
- }
- }
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-v")) {
- puts("sdep-"VERSION);
- exit(0);
- } else if (!strcmp(argv[i], "-d")) {
- puts(default_format);
- exit(0);
- } else if (!strcmp(argv[i], "-s")) {
- str_copy(op.separator, argv[++i], MAXLEN);
- } else if (!strcmp(argv[i], "-f")) {
- if (i+1 >= argc ||
- strptime(argv[i+1], op.format_in, &op.from) == NULL)
- op.from.tm_year = -1000000000; /* Very large number */
- else
- i++;
- } else if (!strcmp(argv[i], "-t")) {
- if (i+1 >= argc ||
- strptime(argv[i+1], op.format_in, &op.to) == NULL)
- op.to.tm_year = 1000000000; /* Very small number */
- else
- i++;
- } else if (!strcmp(argv[i], "-w")) {
- op.format_out = argv[++i];
- } else if (argv[i][0] != '+' && strlen(argv[i]) != 0) {
- fprintf(stderr, "usage: sdep [-dv]");
- fprintf(stderr, " [+format] [-f [date]] [-t [date]]");
- fprintf(stderr, " [-w format] [-s string]\n");
- exit(1);
- }
- }
-
- return op;
-}
-
-/*
- * Copy up to n characters of the string str to dst and append '\0'.
- * Suggested by NRK.
- */
-static void
-str_copy(char *dst, char *src, int n)
-{
- if (memccpy(dst, src, '\0', n) == NULL)
- dst[n-1] = '\0';
-}
-
-static char *
-str_trim(char *t)
-{
- char *s;
-
- for (s = &t[strlen(t)-1]; s != t && is_space(*s); *s = '\0', s--);
- for (; *t != '\0' && is_space(*t); t++);
-
- return t;
-}
-
-static void
-write_output(Options op, Event *ev, int n)
-{
- char outline[MAXLEN];
- int i;
-
- for (i = 0; i < n; i++)
- printf("%s\n", format_line(ev[i], op, outline));
-}
-
-int
-main(int argc, char *argv[])
-{
- Options op;
- EventList evlist = {0};
- Event *selected;
-
- op = read_op(argc, argv);
- read_input(op, &evlist);
- selected = malloc(sizeof(Event) * evlist.count);
- write_output(op, selected, events_in_range(&evlist, op, selected));
-
- return 0;
-}