tfirst commit - stopwatch - simple timer for console or x root window | |
git clone git://src.adamsgaard.dk/stopwatch | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 3390af26250ccad0fd7e796c2325c94f5dbe538c | |
Author: Anders Damsgaard <[email protected]> | |
Date: Wed, 4 Nov 2020 14:56:30 +0100 | |
first commit | |
Diffstat: | |
A LICENSE | 15 +++++++++++++++ | |
A Makefile | 63 +++++++++++++++++++++++++++++… | |
A README | 18 ++++++++++++++++++ | |
A stopwatch.1 | 45 +++++++++++++++++++++++++++++… | |
A stopwatch.c | 105 +++++++++++++++++++++++++++++… | |
5 files changed, 246 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/LICENSE b/LICENSE | |
t@@ -0,0 +1,15 @@ | |
+ISC License | |
+ | |
+Copyright (c) 2020 Anders Damsgaard <[email protected]> | |
+ | |
+Permission to use, copy, modify, and/or distribute this software for any | |
+purpose with or without fee is hereby granted, provided that the above | |
+copyright notice and this permission notice appear in all copies. | |
+ | |
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
diff --git a/Makefile b/Makefile | |
t@@ -0,0 +1,63 @@ | |
+.POSIX: | |
+ | |
+NAME = stopwatch | |
+VERSION = 0.1 | |
+ | |
+# paths | |
+PREFIX = /usr/local | |
+MANPREFIX = ${PREFIX}/share/man | |
+DOCPREFIX = ${PREFIX}/share/doc/${NAME} | |
+ | |
+BIN = ${NAME} | |
+SRC = ${BIN:=.c} | |
+MAN1 = ${BIN:=.1} | |
+DOC = \ | |
+ LICENSE\ | |
+ README | |
+ | |
+all: ${BIN} | |
+ | |
+CFLAGS = -DVERSION=\"${VERSION}\" -I/usr/X11R6/include | |
+LDFLAGS = -L/usr/X11R6/lib -lX11 | |
+ | |
+${BIN}: ${@:=.o} | |
+ | |
+.o: | |
+ ${CC} ${LDFLAGS} -o $@ $< | |
+ | |
+.c.o: | |
+ ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ -c $< | |
+ | |
+dist: | |
+ rm -rf "${NAME}-${VERSION}" | |
+ mkdir -p "${NAME}-${VERSION}" | |
+ cp -f ${MAN1} ${DOC} ${SRC} Makefile "${NAME}-${VERSION}" | |
+ tar cf - "${NAME}-${VERSION}" | gzip -c > "${NAME}-${VERSION}.tar.gz" | |
+ rm -rf "${NAME}-${VERSION}" | |
+ | |
+clean: | |
+ rm -f ${BIN} ${OBJ} | |
+ | |
+install: | |
+ # installing executable files. | |
+ mkdir -p "${DESTDIR}${PREFIX}/bin" | |
+ cp -f ${BIN} "${DESTDIR}${PREFIX}/bin" | |
+ for f in ${BIN}; do chmod 755 "${DESTDIR}${PREFIX}/bin/$$f"; done | |
+ # installing documentation files. | |
+ mkdir -p "${DESTDIR}${DOCPREFIX}" | |
+ cp -f ${DOC} "${DESTDIR}${DOCPREFIX}" | |
+ # installing manual pages for general commands: section 1. | |
+ mkdir -p "${DESTDIR}${DOCPREFIX}/man1" | |
+ cp -f ${MAN1} "${DESTDIR}${MANPREFIX}/man1" | |
+ for m in ${MAN1}; do chmod 644 "${DESTDIR}${MANPREFIX}/man1/$$m"; done | |
+ | |
+uninstall: | |
+ # removing executable files. | |
+ for f in ${BIN}; do rm -f "${DESTDIR}${PREFIX}/bin/$$f"; done | |
+ # removing documentation files. | |
+ for d in ${DOC}; do rm -f "${DESTDIR}${DOCPREFIX}/$$d"; done | |
+ -rmdir "${DESTDIR}${DOCPREFIX}" | |
+ # removing manual pages. | |
+ for m in ${MAN1}; do rm -f "${DESTDIR}${MANPREFIX}/man1/$$m"; done | |
+ | |
+.PHONY: all clean dist install uninstall | |
diff --git a/README b/README | |
t@@ -0,0 +1,18 @@ | |
+# stopwatch | |
+ | |
+About: A simple stopwatch which can print the output to the terminal or | |
+ the X root window parameter. The latter is used for setting the | |
+ dwm(1) title bar. | |
+ | |
+Compiling: `make && make install` | |
+ (optionally prefix the install comman with sudo(1) or doas(1)) | |
+ | |
+Compatibility: Tested on OpenBSD 6.8 | |
+ | |
+Documentation: `man 1 stopwatch` | |
+ | |
+Copyright: See LICENSE | |
+ | |
+Author: Anders Damsgaard <[email protected]> | |
+ git://src.adamsgaard.dk/stopwatch | |
+ https://src.adamsgaard.dk/stopwatch | |
diff --git a/stopwatch.1 b/stopwatch.1 | |
t@@ -0,0 +1,45 @@ | |
+.Dd $Mdocdate$ | |
+.Dt STOPWATCH 1 | |
+.Os | |
+.Sh NAME | |
+.Nm stopwatch | |
+.Nd reports elapsed time after launch. | |
+.Sh SYNOPSIS | |
+.Nm | |
+.Op Fl p Ar prefix | |
+.Op Fl P Ar postfix | |
+.Op Fl i Ar interval | |
+.Op Fl x | |
+.Sh DESCRIPTION | |
+The | |
+.Nm | |
+prints the elapsed time to standard output by default. The time | |
+is written in the format "%S s" for elapsed durations less than one | |
+minute long, "%M:%SS" for durations less than one hour, and | |
+"%H:%MM:%SS" for all longer durations. | |
+.Pp | |
+The options are as follows: | |
+.Bl -tag -width Ds | |
+.It Fl p Ar prefix | |
+Print the | |
+.Ar prefix | |
+string before the time stamp. | |
+.It Fl P Ar postfix | |
+Print the | |
+.Ar postfix | |
+string after the time stamp. | |
+.It Fl i Ar interval | |
+update the elapsed time with this interval in seconds. | |
+.It Fl x | |
+write the output to the X root window parameter, which | |
+.Xr dwm 1 | |
+uses as status line. | |
+.Sh EXIT STATUS | |
+.Nm | |
+exits with 0 on success, and >0 if a a runtime error occurs. | |
+.Sh SEE ALSO | |
+.Xr dwm 1 | |
+.Xr spoon 1 | |
+.Xr xsetroot 1 | |
+.Sh AUTHORS | |
+.An Anders Damsgaard Aq Mt [email protected] | |
diff --git a/stopwatch.c b/stopwatch.c | |
t@@ -0,0 +1,105 @@ | |
+#include <stdio.h> | |
+#include <stdlib.h> | |
+#include <limits.h> | |
+#include <unistd.h> | |
+#include <time.h> | |
+#include <string.h> | |
+#include <err.h> | |
+#include <X11/Xlib.h> | |
+ | |
+void | |
+usage(char *argv0) | |
+{ | |
+ errx(1, "usage: %s [-p prefix] [-P postfix] [-i interval] [-x]", argv0… | |
+} | |
+ | |
+void | |
+format_time(char *out, size_t outsiz, time_t t_elapsed, char *prefix, char *po… | |
+{ | |
+ time_t h = 0, m = 0, s = 0; | |
+ | |
+ h = t_elapsed / 3600; | |
+ m = (t_elapsed % 3600) / 60; | |
+ s = t_elapsed % 60; | |
+ | |
+ if (h > 0) | |
+ snprintf(out, outsiz, "%s%lld:%02lld:%02lld%s", | |
+ prefix, h, m, s, postfix); | |
+ else if (m > 0) | |
+ snprintf(out, outsiz, "%s%lld:%02lld%s", prefix, m, s, postfix… | |
+ else | |
+ snprintf(out, outsiz, "%s%lld s%s", prefix, s, postfix); | |
+} | |
+ | |
+void | |
+print_loop(unsigned int interval, char *prefix, char *postfix) | |
+{ | |
+ char buf[LINE_MAX]; | |
+ time_t t_start = time(NULL); | |
+ | |
+ while (1) { | |
+ format_time(buf, sizeof(buf), time(NULL) - t_start, prefix, po… | |
+ printf("\r%s\n", buf); | |
+ fflush(stdout); | |
+ sleep(interval); | |
+ } | |
+} | |
+ | |
+void | |
+xroot_loop(unsigned int interval, char *prefix, char *postfix) | |
+{ | |
+ Display *dpy; | |
+ char buf[LINE_MAX]; | |
+ time_t t_start = time(NULL); | |
+ | |
+ dpy = XOpenDisplay(NULL); | |
+ if (dpy == NULL) | |
+ errx(1, "cannot open display"); | |
+ while (1) { | |
+ format_time(buf, sizeof(buf), time(NULL) - t_start, prefix, po… | |
+ XStoreName(dpy, DefaultRootWindow(dpy), buf); | |
+ XSync(dpy, False); | |
+ sleep(interval); | |
+ } | |
+} | |
+ | |
+int | |
+main(int argc, char *argv[]) | |
+{ | |
+ int ch, xflag = 0; | |
+ unsigned int interval = 1; | |
+ char prefix[LINE_MAX] = "", postfix[LINE_MAX] = ""; | |
+ const char *errstr; | |
+ | |
+ while ((ch = getopt(argc, argv, "p:P:i:x")) != -1) { | |
+ switch (ch) { | |
+ case 'p': | |
+ strlcpy(prefix, optarg, sizeof(prefix)); | |
+ break; | |
+ case 'P': | |
+ strlcpy(postfix, optarg, sizeof(postfix)); | |
+ break; | |
+ case 'i': | |
+ interval = strtonum(optarg, 1, UINT_MAX, &errstr); | |
+ if (errstr != NULL) | |
+ errx(1, "interval is %s: %s", errstr, optarg); | |
+ break; | |
+ case 'x': | |
+ xflag = 1; | |
+ break; | |
+ default: | |
+ usage(argv[0]); | |
+ } | |
+ } | |
+ argc -= optind; | |
+ argv += optind; | |
+ if (argc > 0) | |
+ usage(argv[0]); | |
+ | |
+ if (xflag) | |
+ xroot_loop(interval, prefix, postfix); | |
+ else | |
+ print_loop(interval, prefix, postfix); | |
+ | |
+ return 0; | |
+} |