Compare commits

..

No commits in common. "168b4f092caff12d2dddcf24fd85718d48e44a9a" and "bf82caf6e00f92dce995f9838337ce249948c871" have entirely different histories.

13 changed files with 432 additions and 82 deletions

30
.gitignore vendored Normal file
View File

@ -0,0 +1,30 @@
# Object files
*.o
*.ko
*.obj
*.elf
# Libraries
*.lib
*.a
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
/spt
# vim
*.swp
*~
config.h

View File

@ -1,5 +1,4 @@
Copyright (c) 2015-2020, Ivan Tham <pickfire@riseup.net> Copyright (c) 2015-2020, Ivan Tham <pickfire@riseup.net>
2023- , Nuño Sempere <nuno.semperelh@protonmail.com>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

59
Makefile Normal file
View File

@ -0,0 +1,59 @@
# spt - simple pomodoro timer
# See LICENSE file for copyright and license details.
include config.mk
SRC = spt.c
OBJ = ${SRC:.c=.o}
all: options spt
options:
@echo spt build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
spt: ${OBJ}
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@rm -f ${SRC:.c=} ${OBJ} spt-${VERSION}.tar.xz
dist: clean
@echo creating dist tarball
@mkdir -p spt-${VERSION}
@cp -R LICENSE Makefile README config.mk config.def.h spt.info spt.1 ${SRC} spt-${VERSION}
@tar -cf spt-${VERSION}.tar spt-${VERSION}
@xz spt-${VERSION}.tar
@rm -rf spt-${VERSION}
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f spt ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/spt
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed "s/VERSION/${VERSION}/g" < spt.1 > ${DESTDIR}${MANPREFIX}/man1/spt.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/spt.1
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/spt
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/spt.1
.PHONY: all options clean dist install uninstall

View File

@ -1,26 +1,36 @@
# pomo - a simple pomodoro timer spt - simple pomodoro timer
===========================
spt is a simple timer that uses the pomodoro technique that doubles your
efficiency.
## about Features
--------
- Get the jobs done quicker than ever
- Keeps you free like a dog
- Able to show remaining time
pomo is a simple timer that uses the pomodoro technique. It is based on [spt](https://github.com/pickfire/spt), which is a bit less simple. Installation
------------
Edit config.mk to match your local setup (spt is installed into the /usr/local
namespace by default).
## dependencies Afterwards enter the following command to build and install spt (if necessary
as root):
Instead of inotify, this pomodoro timer uses [sent](https://tools.suckless.org/sent/), displaying messages to the user by spawning a process that calls `echo 'msg' | sent`. make clean install
## installation See the man pages for additional details.
Read pomo.c, then: Configuration
-------------
The configuration of spt is done by creating a custom config.h and
(re)compiling the source code. By default, the timer runs by 4
pomodoro timer (25 mins) with subsequent rests in between (15 mins)
followed by a long rest (5 mins) in an infinite loop.
``` Links
make -----
sudo make install http://pomodorotechnique.com/
```
## usage
In a terminal, call the "pomo" command. Then, an initial message will appear in its own window. Close it and start working. By default, the timer runs by 4 pomodoro timer (25 mins) with subsequent rests in between (5 mins) followed by a long rest (15 mins) in an infinite loop. The project is licensed under the MIT license.
## configuration
read through the <60 lines of C, and change as appropriate. If this functionality is too simple, consider looking at [spt](https://github.com/pickfire/spt) instead.

1
TODO Normal file
View File

@ -0,0 +1 @@
Good luck! Nothing TODO for now.

40
arg.h Normal file
View File

@ -0,0 +1,40 @@
/*
* Copy me if you can.
* by 20h
*/
#ifndef __ARG_H__
#define __ARG_H__
extern char *argv0;
#define USED(x) ((void)(x))
#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
argv[0] && argv[0][1]\
&& argv[0][0] == '-';\
argc--, argv++) {\
char _argc;\
char **_argv;\
if (argv[0][1] == '-' && argv[0][2] == '\0') {\
argv++;\
argc--;\
break;\
}\
for (argv[0]++, _argv = argv; argv[0][0];\
argv[0]++) {\
if (_argv != argv)\
break;\
_argc = argv[0][0];\
switch (_argc)
#define ARGEND }\
USED(_argc);\
}\
USED(argv);\
USED(argc);
#define EARGF(x) ((argv[1] == NULL)? ((x), abort(), (char *)0) :\
(argc--, argv++, argv[0]))
#endif

22
config.def.h Normal file
View File

@ -0,0 +1,22 @@
/* See LICENSE file for copyright and license details. */
/* Notification, remove DNOTIFY in config.mk if you don't want it */
static char *notifycmd = ""; /* Uses given command if not compiled by DNOTIFY */
static char *notifyext = ""; /* Notify with extra command (eg. play an alarm) */
/*
* This is the array which defines all the timer that will be used.
* It will be repeated after all of it is executed.
*/
static Timers timers[] = {
/* timer(s) comment */
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 900, "Time to take some nap!"},
};

24
config.mk Normal file
View File

@ -0,0 +1,24 @@
# spt version
VERSION = 0.5
# Customize below to fit your system
# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
INCS = -I. -I/usr/include
LIBS = -L/usr/lib
# libnotify, comment if you don't want it
DEFS = -DNOTIFY
INCS+= `pkg-config --cflags libnotify`
LIBS+= `pkg-config --libs libnotify`
# flags
CPPFLAGS += -DVERSION=\"${VERSION}\" -D_POSIX_C_SOURCE=199309
CFLAGS += -g -std=c99 -pedantic -Wall -Os ${INCS} ${DEFS} ${CPPFLAGS}
LDFLAGS += -g ${LIBS}
# compiler and linker
CC ?= cc

6
contrib/notify-macos Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
# A notification wrapper for MacOS. It will appear in Notification
# Center as owned by Script Editor.
#
# usage: spt -n ./notify-macos
osascript -e "display notification \"$2\" with title \"$1\""

View File

@ -1,8 +0,0 @@
build:
gcc pomo.c -o pomo
install:
mv ./pomo /bin/pomo
lint:
clang-tidy pomo.c --

56
pomo.c
View File

@ -1,56 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_MSG_LEN 100
#define LEN(a) (sizeof(a) / sizeof(a[0]))
typedef struct {
unsigned int t;
char *msg;
} Timers;
static Timers timers[] = {
/* timer(s) comment */
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 300, "Time to start resting!"},
{ 1500, "Time to start working!"},
{ 900, "Time to take a longer rest!" },
};
void spawn(char *argv[]){
if (fork() == 0) {
// we need to fork the process so that
// when we exit the sent screen
// this program continues.
setsid();
execvp(argv[0], argv);
perror(" failed");
exit(0);
}
}
void display_message(char *msg){
char sh_command[MAX_MSG_LEN];
snprintf(sh_command, MAX_MSG_LEN, "echo '%s' | sent", msg); // NOLINT: We are being carefull here by considering MAX_MSG_LEN explicitly.
printf("%s", sh_command);
char *spawn_args[] = {
"/bin/sh",
"-c",
sh_command,
NULL
};
spawn(spawn_args);
// fprintf(stderr, "%s\n", msg);
}
int main(int argc, char *argv[]){
for(int i=0; ; i = (i+1) % LEN(timers)){
display_message(timers[i].msg);
sleep(timers[i].t);
}
}

51
spt.1 Normal file
View File

@ -0,0 +1,51 @@
.TH SPT 1 spt\-VERSION
.SH NAME
spt \- simple pomodoro timer
.SH SYNOPSIS
.B spt
.RB [ \-e
.IR notifyext ]
.RB [ \-n
.IR notifycmd ]
.RB [ \-v ]
.SH DESCRIPTION
.B spt
is a simple timer that uses pomodoro technique with desktop notification to
double your efficiency.
.B spt
receives 2 signals:
.P
.RS
.B SIGUSR1
\- show remaining time, state
.br
.B SIGUSR2
\- play/pause the timer
.RE
.SH OPTIONS
.TP
.BI \-e " notifyext"
Execute
.I notifycmd
when timer starts ticking.
.TP
.BI \-n " notifycmd"
Execute
.I notifycmd
if not compiled with
.IR "-DNOTIFY".
.TP
.BI \-v
Prints version information to stderr, then exits.
.SH TIMER
4 pomodoro timer (
.B 25 min.
) with subsequent rests in between (
.B 5 min.
) and followed by a long rest (
.B 15 min.
) in an infinite loop.
.SH EXAMPLES
Use system notify_send and play a music without libnotify:
.IP
spt -e 'aplay alarm.wav' -n 'notify-send'

172
spt.c Normal file
View File

@ -0,0 +1,172 @@
/* See LICENSE file for copyright and license details. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#ifdef NOTIFY
#include <libnotify/notify.h>
#endif /* NOTIFY */
#include "arg.h"
char *argv0;
/* macros */
#define LEN(a) (sizeof(a) / sizeof(a[0]))
typedef struct {
unsigned int tmr;
char *cmt;
} Timers;
#include "config.h"
volatile static sig_atomic_t display, suspend;
/* function declarations */
static void die(const char *errstr, ...);
static void spawn(char *argv[]);
static void notify_send(char *cmt);
static void display_state(int remaining, int suspend);
static void toggle_display(int sigint);
static void toggle_suspend(int sigint);
static void usage(void);
/* functions implementations */
void
die(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(1);
}
void
spawn(char *argv[])
{
if (fork() == 0) {
setsid();
execvp(argv[0], argv);
die("spt: execvp %s\n", argv[0]);
perror(" failed");
exit(0);
}
}
void
notify_send(char *cmt)
{
if (strcmp(notifycmd, ""))
spawn((char *[]) { notifycmd, "spt", cmt, NULL });
#ifdef NOTIFY
else {
notify_init("spt");
NotifyNotification *n = notify_notification_new("spt", cmt, \
"dialog-information");
notify_notification_show(n, NULL);
g_object_unref(G_OBJECT(n));
notify_uninit();
}
#endif /* NOTIFY */
if (strcmp(notifyext, "")) /* extra commands to use */
spawn((char *[]) { "/bin/sh", "-c", notifyext, NULL });
}
void
display_state(int remaining, int suspend)
{
char buf[29];
snprintf(buf, 29, "Remaining: %02d:%02d %s",
remaining / 60,
remaining % 60,
(suspend) ? "" : "");
notify_send(buf);
display = 0;
}
void
toggle_display(int sigint)
{
display = 1;
}
void
toggle_suspend(int sigint)
{
suspend ^= 1;
}
void
usage(void)
{
die("usage: %s [-e notifyext] [-n notifycmd] [-v]\n", argv0);
}
int
main(int argc, char *argv[])
{
struct timespec remaining;
struct sigaction sa;
sigset_t emptymask;
int i;
ARGBEGIN {
case 'e':
notifyext = EARGF(usage());
break;
case 'n':
notifycmd = EARGF(usage());
break;
case 'v':
die("spt " VERSION " © 2015-2020 spt engineers, "
"see LICENSE for details\n");
default:
usage();
} ARGEND;
/* add SIGUSR1 handler: remaining_time */
sa.sa_handler = toggle_display;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
die("cannot associate SIGUSR1 to handler\n");
/* add SIGUSR2 handler: toggle */
sa.sa_handler = toggle_suspend;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGUSR2, &sa, NULL) == -1)
die("cannot associate SIGUSR2 to handler\n");
sigemptyset(&emptymask);
for (i = 0; ; i = (i + 1) % LEN(timers)) {
notify_send(timers[i].cmt);
remaining.tv_sec = timers[i].tmr;
remaining.tv_nsec = 0;
while (remaining.tv_sec) {
if (display)
display_state(remaining.tv_sec, suspend);
if (suspend)
sigsuspend(&emptymask);
else
if (nanosleep(&remaining, &remaining) == 0)
remaining.tv_sec = remaining.tv_nsec = 0;
}
}
return 0;
}