Simple Time Tracker
This commit is contained in:
commit
53948fa278
8 changed files with 555 additions and 0 deletions
20
LICENSE
Normal file
20
LICENSE
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
© 2016 Simon Lieb <pips@e5150.fr>
|
||||||
|
|
||||||
|
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.
|
||||||
49
Makefile
Normal file
49
Makefile
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
# stt - simple time tracker
|
||||||
|
# See LICENSE file for copyright and license details.
|
||||||
|
|
||||||
|
include config.mk
|
||||||
|
|
||||||
|
SRC = stt.c
|
||||||
|
OBJ = ${SRC:.c=.o}
|
||||||
|
|
||||||
|
all: options stt
|
||||||
|
|
||||||
|
options:
|
||||||
|
@echo stt build options:
|
||||||
|
@echo "CFLAGS = ${CFLAGS}"
|
||||||
|
@echo "LDFLAGS = ${LDFLAGS}"
|
||||||
|
@echo "CC = ${CC}"
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
@echo CC $<
|
||||||
|
@${CC} -c ${CFLAGS} $<
|
||||||
|
|
||||||
|
${OBJ}: config.mk
|
||||||
|
|
||||||
|
stt: ${OBJ}
|
||||||
|
@echo CC -o $@
|
||||||
|
@${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@echo cleaning
|
||||||
|
@rm -f stt ${OBJ} stt-${VERSION}.tar.gz
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
@echo creating dist tarball
|
||||||
|
@mkdir -p stt-${VERSION}
|
||||||
|
@cp -R LICENSE Makefile config.mk ${SRC} stt.1 arg.h README.md stt-${VERSION}
|
||||||
|
@tar -cf stt-${VERSION}.tar stt-${VERSION}
|
||||||
|
@gzip stt-${VERSION}.tar
|
||||||
|
@rm -rf stt-${VERSION}
|
||||||
|
|
||||||
|
install: all
|
||||||
|
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
|
||||||
|
@mkdir -p ${DESTDIR}${PREFIX}/bin
|
||||||
|
@cp -f stt ${DESTDIR}${PREFIX}/bin
|
||||||
|
@chmod 755 ${DESTDIR}${PREFIX}/bin/stt
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
|
||||||
|
@rm -f ${DESTDIR}${PREFIX}/bin/stt
|
||||||
|
|
||||||
|
.PHONY: all options clean dist install uninstall
|
||||||
17
README.md
Normal file
17
README.md
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
stt
|
||||||
|
====
|
||||||
|
|
||||||
|
Simple Time Tracker
|
||||||
|
|
||||||
|
Install
|
||||||
|
-------
|
||||||
|
|
||||||
|
# make clean install
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
$ stt -a task # start task
|
||||||
|
$ stt -s # stop task
|
||||||
|
$ stt [-l] # print report
|
||||||
|
|
||||||
5
TODO.md
Normal file
5
TODO.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
* play with <sys/tree.h> instead of home made tree funcs
|
||||||
|
* add argument to list previous/arbitraty days
|
||||||
|
* easier past task management than `date -d <date> +%s && vim ~/.ttime`
|
||||||
|
* add some more complex task description (i.e: task@project)
|
||||||
|
* use task@project to group task in reports
|
||||||
48
arg.h
Normal file
48
arg.h
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Copy me if you can.
|
||||||
|
* by 20h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ARG_H__
|
||||||
|
#define ARG_H__
|
||||||
|
|
||||||
|
extern char *argv0;
|
||||||
|
|
||||||
|
/* use main(int argc, char *argv[]) */
|
||||||
|
#define ARGBEGIN for (argv0 = *argv, argv++, argc--;\
|
||||||
|
argv[0] && argv[0][0] == '-'\
|
||||||
|
&& argv[0][1];\
|
||||||
|
argc--, argv++) {\
|
||||||
|
char argc_;\
|
||||||
|
char **argv_;\
|
||||||
|
int brk_;\
|
||||||
|
if (argv[0][1] == '-' && argv[0][2] == '\0') {\
|
||||||
|
argv++;\
|
||||||
|
argc--;\
|
||||||
|
break;\
|
||||||
|
}\
|
||||||
|
for (brk_ = 0, argv[0]++, argv_ = argv;\
|
||||||
|
argv[0][0] && !brk_;\
|
||||||
|
argv[0]++) {\
|
||||||
|
if (argv_ != argv)\
|
||||||
|
break;\
|
||||||
|
argc_ = argv[0][0];\
|
||||||
|
switch (argc_)
|
||||||
|
#define ARGEND }\
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ARGC() argc_
|
||||||
|
|
||||||
|
#define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\
|
||||||
|
((x), abort(), (char *)0) :\
|
||||||
|
(brk_ = 1, (argv[0][1] != '\0')?\
|
||||||
|
(&argv[0][1]) :\
|
||||||
|
(argc--, argv++, argv[0])))
|
||||||
|
|
||||||
|
#define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\
|
||||||
|
(char *)0 :\
|
||||||
|
(brk_ = 1, (argv[0][1] != '\0')?\
|
||||||
|
(&argv[0][1]) :\
|
||||||
|
(argc--, argv++, argv[0])))
|
||||||
|
|
||||||
|
#endif
|
||||||
19
config.mk
Normal file
19
config.mk
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# stt version
|
||||||
|
VERSION = 0.1
|
||||||
|
|
||||||
|
# Customize below to fit your system
|
||||||
|
|
||||||
|
# paths
|
||||||
|
PREFIX = /usr/local
|
||||||
|
|
||||||
|
# includes and libs
|
||||||
|
INCS =
|
||||||
|
LIBS =
|
||||||
|
|
||||||
|
# flags
|
||||||
|
CPPFLAGS = -DVERSION=\"${VERSION}\"
|
||||||
|
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
|
||||||
|
LDFLAGS = -static -s ${LIBS}
|
||||||
|
|
||||||
|
# compiler and linker
|
||||||
|
CC = cc
|
||||||
35
stt.1
Normal file
35
stt.1
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
.TH stt 1 stt\-VERSION
|
||||||
|
.SH NAME
|
||||||
|
stt \- Simple time tracker
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B stt
|
||||||
|
.RB [ \-v ]
|
||||||
|
.RB [ \-h ]
|
||||||
|
.RB [ \-a
|
||||||
|
.IR task " |"
|
||||||
|
.RB \-s " |"
|
||||||
|
.RB \-l ]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B stt
|
||||||
|
keeps track of tasks during a work day.
|
||||||
|
.PP
|
||||||
|
Without operand, day report is printed, as with
|
||||||
|
.B -l
|
||||||
|
option.
|
||||||
|
.SH OPTIONS
|
||||||
|
.TP
|
||||||
|
.BI \-a " task"
|
||||||
|
Registers given task as active. Will also stop previous active task.
|
||||||
|
.TP
|
||||||
|
.B \-s
|
||||||
|
Stops current active task.
|
||||||
|
.TP
|
||||||
|
.B \-l
|
||||||
|
Prints day report, for each tasks name, start time, end time or state if
|
||||||
|
still running and duration (in decimal hours) is displayed.
|
||||||
|
.TP
|
||||||
|
.B \-h
|
||||||
|
Prints synopsis help.
|
||||||
|
.TP
|
||||||
|
.B \-v
|
||||||
|
Prints version information.
|
||||||
362
stt.c
Normal file
362
stt.c
Normal file
|
|
@ -0,0 +1,362 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "arg.h"
|
||||||
|
|
||||||
|
#ifndef VERSION
|
||||||
|
#define VERSION "dev"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *argv0;
|
||||||
|
|
||||||
|
static char *timesfile = ".ttimes";
|
||||||
|
|
||||||
|
struct timesnode {
|
||||||
|
char *task;
|
||||||
|
time_t starttime;
|
||||||
|
time_t endtime;
|
||||||
|
struct timesnode *left;
|
||||||
|
struct timesnode *right;
|
||||||
|
signed int height;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* functions declarations */
|
||||||
|
static void usage(void);
|
||||||
|
|
||||||
|
FILE *opentimesfile();
|
||||||
|
|
||||||
|
struct timesnode *loadtimes(FILE *, struct timesnode *);
|
||||||
|
void writetimes(FILE *, struct timesnode *);
|
||||||
|
struct timesnode *timesnode_add(struct timesnode *, const char *, time_t, time_t);
|
||||||
|
struct timesnode *timesnode_stop(struct timesnode *, time_t);
|
||||||
|
int timesnode_max(int, int);
|
||||||
|
int timesnode_heigh(struct timesnode *);
|
||||||
|
int timesnode_getbalance(struct timesnode *);
|
||||||
|
struct timesnode *timesnode_rightrotate(struct timesnode *);
|
||||||
|
struct timesnode *timesnode_leftrotate(struct timesnode *);
|
||||||
|
void timesnode_print(struct timesnode *, time_t);
|
||||||
|
|
||||||
|
void
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s [-v] [-h] [-a task | -s | -l]\n", argv0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *
|
||||||
|
opentimesfile()
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
fp = fopen(timesfile, "r+");
|
||||||
|
|
||||||
|
if (fp == NULL) {
|
||||||
|
//int oldcwd;
|
||||||
|
struct passwd *passwd;
|
||||||
|
|
||||||
|
//oldcwd = dirfd(opendir("."));
|
||||||
|
|
||||||
|
passwd = getpwuid(getuid());
|
||||||
|
chdir(passwd->pw_dir);
|
||||||
|
|
||||||
|
fp = fopen(timesfile, "a+");
|
||||||
|
|
||||||
|
if (fp == NULL) {
|
||||||
|
perror("fopen failed");
|
||||||
|
}
|
||||||
|
//fchdir(oldcwd);
|
||||||
|
}
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr, "%s: Error opening times file\n", argv0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timesnode *
|
||||||
|
loadtimes(FILE * fp, struct timesnode * p)
|
||||||
|
{
|
||||||
|
char *readline, *line, *tmp;
|
||||||
|
time_t starttime, endtime;
|
||||||
|
char *task;
|
||||||
|
size_t linesize;
|
||||||
|
ssize_t linelen;
|
||||||
|
|
||||||
|
rewind(fp);
|
||||||
|
|
||||||
|
line = readline = NULL;
|
||||||
|
linesize = 0;
|
||||||
|
while ((linelen = getline(&readline, &linesize, fp)) != -1) {
|
||||||
|
line = strdup(readline);
|
||||||
|
tmp = strsep(&line, ";");
|
||||||
|
starttime = atoi(tmp);
|
||||||
|
|
||||||
|
if (starttime == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp = strsep(&line, ";");
|
||||||
|
endtime = atoi(tmp);
|
||||||
|
|
||||||
|
task = strdup(line);
|
||||||
|
task[strlen(task) - 1] = '\0';
|
||||||
|
|
||||||
|
p = timesnode_add(p, task, starttime, endtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
writetimes(FILE * fp, struct timesnode * p)
|
||||||
|
{
|
||||||
|
if (p == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p->left != NULL) {
|
||||||
|
writetimes(fp, p->left);
|
||||||
|
}
|
||||||
|
fprintf(fp, "%lld;%lld;%s\n", p->starttime, p->endtime, p->task);
|
||||||
|
|
||||||
|
if (p->right != NULL) {
|
||||||
|
writetimes(fp, p->right);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
timesnode_max(int a, int b)
|
||||||
|
{
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
timesnode_heigh(struct timesnode * p)
|
||||||
|
{
|
||||||
|
if (p == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return p->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
timesnode_getbalance(struct timesnode * p)
|
||||||
|
{
|
||||||
|
if (p == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (timesnode_heigh(p->left) + (p->left != NULL)) - (timesnode_heigh(p->right) + (p->right != NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timesnode *
|
||||||
|
timesnode_rightrotate(struct timesnode * p)
|
||||||
|
{
|
||||||
|
struct timesnode *leftchild;
|
||||||
|
struct timesnode *subrightchild;
|
||||||
|
|
||||||
|
leftchild = p->left;
|
||||||
|
subrightchild = leftchild->right;
|
||||||
|
|
||||||
|
leftchild->right = p;
|
||||||
|
p->left = subrightchild;
|
||||||
|
|
||||||
|
p->height = (p->left != NULL || p->right != NULL) ? 1 + timesnode_max(timesnode_heigh(p->left), timesnode_heigh(p->right)) : 0;
|
||||||
|
leftchild->height = 1 + timesnode_max(timesnode_heigh(leftchild->left), timesnode_heigh(leftchild->right));
|
||||||
|
|
||||||
|
return leftchild;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timesnode *
|
||||||
|
timesnode_leftrotate(struct timesnode * p)
|
||||||
|
{
|
||||||
|
struct timesnode *rightchild;
|
||||||
|
struct timesnode *subleftchild;
|
||||||
|
|
||||||
|
rightchild = p->right;
|
||||||
|
subleftchild = rightchild->left;
|
||||||
|
|
||||||
|
rightchild->left = p;
|
||||||
|
p->right = subleftchild;
|
||||||
|
|
||||||
|
p->height = (p->left != NULL || p->right != NULL) ? 1 + timesnode_max(timesnode_heigh(p->left), timesnode_heigh(p->right)) : 0;
|
||||||
|
rightchild->height = 1 + timesnode_max(timesnode_heigh(rightchild->left), timesnode_heigh(rightchild->right));
|
||||||
|
|
||||||
|
return rightchild;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timesnode *
|
||||||
|
timesnode_add(struct timesnode * p, const char *task, time_t starttime, time_t endtime)
|
||||||
|
{
|
||||||
|
int balance;
|
||||||
|
|
||||||
|
if (p == NULL) {
|
||||||
|
p = (struct timesnode *) malloc(sizeof(struct timesnode));
|
||||||
|
|
||||||
|
p->task = strdup(task);
|
||||||
|
p->starttime = starttime;
|
||||||
|
p->endtime = endtime;
|
||||||
|
p->left = p->right = NULL;
|
||||||
|
p->height = 0;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
} else if (p->starttime > starttime) {
|
||||||
|
p->left = timesnode_add(p->left, task, starttime, endtime);
|
||||||
|
} else {
|
||||||
|
p->right = timesnode_add(p->right, task, starttime, endtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
p->height = 1 + timesnode_max(timesnode_heigh(p->left), timesnode_heigh(p->right));
|
||||||
|
|
||||||
|
balance = timesnode_getbalance(p);
|
||||||
|
|
||||||
|
if (balance > 1 && starttime < p->left->starttime) {
|
||||||
|
return timesnode_rightrotate(p);
|
||||||
|
}
|
||||||
|
if (balance < -1 && starttime > p->right->starttime) {
|
||||||
|
return timesnode_leftrotate(p);
|
||||||
|
}
|
||||||
|
if (balance > 1 && starttime > p->left->starttime) {
|
||||||
|
p->left = timesnode_leftrotate(p->left);
|
||||||
|
return timesnode_rightrotate(p);
|
||||||
|
}
|
||||||
|
if (balance < -1 && starttime < p->right->starttime) {
|
||||||
|
p->right = timesnode_rightrotate(p->right);
|
||||||
|
return timesnode_leftrotate(p);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timesnode *
|
||||||
|
timesnode_stop(struct timesnode * p, time_t endtime)
|
||||||
|
{
|
||||||
|
if (p == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (p->endtime == 0) {
|
||||||
|
p->endtime = endtime;
|
||||||
|
}
|
||||||
|
if (p->left != NULL) {
|
||||||
|
timesnode_stop(p->left, endtime);
|
||||||
|
}
|
||||||
|
if (p->right != NULL) {
|
||||||
|
timesnode_stop(p->right, endtime);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
timesnode_print(struct timesnode * p, time_t aftertime)
|
||||||
|
{
|
||||||
|
time_t *nowtime;
|
||||||
|
int duration = 0;
|
||||||
|
|
||||||
|
if (p == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (p->left != NULL) {
|
||||||
|
timesnode_print(p->left, aftertime);
|
||||||
|
}
|
||||||
|
if (p->starttime > aftertime || p->endtime > aftertime || p->endtime == 0) {
|
||||||
|
printf("task: %s\n", p->task);
|
||||||
|
printf("started at: %s", ctime(&p->starttime));
|
||||||
|
|
||||||
|
if (p->endtime != 0) {
|
||||||
|
printf("ended at: %s", ctime(&p->endtime));
|
||||||
|
|
||||||
|
duration = difftime(p->endtime, p->starttime);
|
||||||
|
|
||||||
|
printf("duration(hours): %.2f\n\n", duration / 3600.0);
|
||||||
|
} else {
|
||||||
|
nowtime = malloc(sizeof(time_t));
|
||||||
|
time(nowtime);
|
||||||
|
printf("still running\n");
|
||||||
|
|
||||||
|
duration = difftime(*nowtime, p->starttime);
|
||||||
|
|
||||||
|
printf("duration(hours): %.2f\n\n", duration / 3600.0);
|
||||||
|
free(nowtime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->right != NULL) {
|
||||||
|
timesnode_print(p->right, aftertime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
unsigned int start, stop, list;
|
||||||
|
char *task;
|
||||||
|
FILE *fp;
|
||||||
|
struct timesnode *timestree;
|
||||||
|
time_t *nowtime;
|
||||||
|
int changed;
|
||||||
|
struct tm today;
|
||||||
|
|
||||||
|
timestree = NULL;
|
||||||
|
task = NULL;
|
||||||
|
changed = start = stop = 0;
|
||||||
|
list = 1;
|
||||||
|
|
||||||
|
nowtime = malloc(sizeof(time_t));
|
||||||
|
|
||||||
|
ARGBEGIN {
|
||||||
|
case 'a': /* start new task - stop current if any */
|
||||||
|
start = 1;
|
||||||
|
stop = 1;
|
||||||
|
list = 0;
|
||||||
|
|
||||||
|
task = EARGF(usage());
|
||||||
|
break;
|
||||||
|
case 's': /* stop current task */
|
||||||
|
start = 0;
|
||||||
|
stop = 1;
|
||||||
|
list = 0;
|
||||||
|
break;
|
||||||
|
case 'l': /* list task */
|
||||||
|
start = 0;
|
||||||
|
stop = 0;
|
||||||
|
list = 1;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
fprintf(stderr, "%s-" VERSION " © 2016 Simon Lieb, see LICENSE for details\n", argv0);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
} ARGEND;
|
||||||
|
|
||||||
|
fp = opentimesfile();
|
||||||
|
|
||||||
|
time(nowtime);
|
||||||
|
timestree = loadtimes(fp, timestree);
|
||||||
|
|
||||||
|
if (stop) {
|
||||||
|
timesnode_stop(timestree, *nowtime);
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
if (task != NULL && start) {
|
||||||
|
timestree = timesnode_add(timestree, task, *nowtime, 0);
|
||||||
|
changed = 1;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
freopen(timesfile, "w", fp);
|
||||||
|
writetimes(fp, timestree);
|
||||||
|
}
|
||||||
|
if (list) {
|
||||||
|
localtime_r(nowtime, &today);
|
||||||
|
|
||||||
|
today.tm_sec = 0;
|
||||||
|
today.tm_min = 0;
|
||||||
|
today.tm_hour = 0;
|
||||||
|
|
||||||
|
timesnode_print(timestree, mktime(&today));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue