--- /dev/null
+*
+!.gitignore
+!LICENSE
+!README.md
+!Makefile
+!*.c
+!*.h
+!*.o
+sqlite3.c
PROG = odot
+CC = gcc
CFILE = $(PROG).c database.c
HEADER = $(PROG).h sqlite3.h
OBJECTS = $(PROG).o database.o task.o sqlite3.o
-CFLAGS = -Wall -lpthread
+LDFLAGS = -L .
+LDLIBS = -lpthread
+CFLAGS = -Wall -Wextra -O2
+CPPFLAGS = -I .
+ALL_CFLAGS = $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS)
sql: sqlite3.c
- gcc sqlite3.c $(CFLAGS) -c
+ $(CC) sqlite3.c $(CFLAGS) -c
header: $(HEADER)
- gcc $(HEADER) $(CFLAGS) -c
+ $(CC) $(HEADER) $(CFLAGS) -c
compile: $(CFILE)
- gcc $(CFILE) $(CFLAGS) -c
+ $(CC) $(CFILE) $(CFLAGS) -c
link: $(OBJECTS)
- gcc $(OBJECTS) $(CFLAGS) -o $(PROG)
+ $(CC) $(OBJECTS) $(CFLAGS) -o $(PROG)
-build: $(CFILE) $(HEADER) sqlite3.c
- gcc $(CFILE) $(HEADER) sqlite3.c $(CFLAGS) -o $(PROG)
+build: $(CFILE) $(HEADER) sqlite3.o
+ $(CC) $(CFILE) sqlite3.o $(CFLAGS) -o $(PROG)
-install: $(CFILE) $(HEADER) $(SQLFILE)
- gcc $(CFILE) $(HEADER) $(SQLFILE) $(CFLAGS) -o $(DESTDIR)/$(PROG)
+install: $(CFILE) $(HEADER) sqlite3.o
+ $(CC) $(CFILE) sqlite3.o $(CFLAGS) -o $(DESTDIR)/$(PROG)
debug: $(CFILE)
- gcc $(CFILE) sqlite3.o $(CFLAGS) -g -o $(PROG)
+ $(CC) $(CFILE) sqlite3.o $(CFLAGS) -ggdb3 -Og -o $(PROG)
clean:
rm *.gch *.o
#include "odot.h"
+extern char *group,
+ *task;
+
+
sqlite3 *accessdb(char *file){
sqlite3 *db;
int err = sqlite3_open(file, &db);
- if (err) {
- fprintf(stderr, "Could not open database: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
+ if (err) sqlerror(db);
return db;
}
-void buildtables(sqlite3 *db){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"CREATE TABLE IF NOT EXISTS Tasks (Task varchar(1000) NOT NULL PRIMARY KEY, Type varchar(100) NOT NULL, Done int NOT NULL DEFAULT 0);");
- int err = sqlite3_exec(db,cmd,NULL,NULL,errmsg);
- if (err) {
- fprintf(stderr, "Could not create table: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
-
- free(cmd);
- return;
-}
-
-
-void addtask(sqlite3 *db, struct task task){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"INSERT INTO Tasks VALUES ( '%s', '%s', 0);",task.task,task.group);
- int err = sqlite3_exec(db,cmd,NULL,NULL,errmsg);
- if (err) {
- fprintf(stderr, "Could not add task: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
-
- free(cmd);
+void sqlcmd(sqlite3 *db, char *cmd){
+ int err = sqlite3_exec(db,cmd,NULL,NULL,NULL);
+ if (err) sqlerror(db);
return;
-}
-
-void removetask(sqlite3 *db, struct task task){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
- sprintf(cmd,"DELETE FROM Tasks WHERE Task = '%s';",task.task);
- int err = sqlite3_exec(db,cmd,NULL,NULL,errmsg);
- if (err) {
- fprintf(stderr, "Could not remove task: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
-
- free(cmd);
- return;
}
-void donetask(sqlite3 *db, struct task task){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"UPDATE Tasks SET Done = 1 WHERE Task = '%s';",task.task);
- int err = sqlite3_exec(db,cmd,NULL,NULL,errmsg);
- if (err) {
- fprintf(stderr, "Could not modify task in db: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
-
- free(cmd);
+void sqlprint(sqlite3 *db, char *cmd){
+ int err = sqlite3_exec(db,cmd,printcallback,0,NULL);
+ if (err) sqlerror(db);
return;
-}
-int printcallback(void *unused,int argc, char **argv, char **name){
- printf("\t[%s] - ", (strcmp(argv[0],"1") == 0) ? "X" : " ");
- for (int i = 1; i < argc; i++){
- printf("%s\t",argv[i]);
- }
- printf("\n");
- return 0;
}
-void print(sqlite3 *db){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"SELECT Done, Type, Task FROM Tasks WHERE Done = 0 ORDER BY Type;");
- printf("TODO:");
- int err = sqlite3_exec(db,cmd,printcallback,0,errmsg);
- if (err) {
- fprintf(stderr, "Could not access db: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
-
- free(cmd);
+void sqlgroup(sqlite3 *db, char *cmd){
+ int err = sqlite3_exec(db,cmd,groupcallback,0,NULL);
+ if (err) sqlerror(db);
return;
+
}
-void printdone(sqlite3 *db){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"SELECT Done, Type, Task FROM Tasks ORDER BY Type;");
- printf("TODO:");
- int err = sqlite3_exec(db,cmd,printcallback,0,errmsg);
- if (err) {
- fprintf(stderr, "Could not access db: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
- free(cmd);
- return;
+void sqlerror(sqlite3 *db) {
+ fprintf(stderr, "%s\n", sqlite3_errmsg(db));
+ sqlite3_close(db);
+ error(1);
}
-void printgroup(sqlite3 *db, struct task t){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"SELECT Done, Type, Task FROM Tasks WHERE (Type = '%s' AND Done = 0) OR Task = '%s' ORDER BY Type;",t.group,t.task);
- printf("TODO:");
- int err = sqlite3_exec(db,cmd,printcallback,0,errmsg);
- if (err) {
- fprintf(stderr, "Could not access db: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
+int printcallback(void *unused,int argc, char **argv, char **name){
+ int i = 1;
+
+ if (argv[2]){
+ char *g = malloc(strlen(argv[1])*sizeof(char));
+ sprintf(g,"%s",argv[1]);
+ if (strcmp(g,group) != 0) {
+ sprintf(group,"%s",argv[1]);
+ printf("\n\t\033[34m%s\033[0m\n",argv[1]);
+ }
+ i = 2;
}
- free(cmd);
- return;
+ printf("\t\033[32m[\033[0m%s\033[32m]\033[0m - ", (strcmp(argv[0],"1") == 0) ? "\033[31;1mX\033[0m" : " ");
+ printf("%s\n",argv[i]);
+ return 0;
}
-void printgroupdone(sqlite3 *db, struct task t){
- char *cmd = malloc(MAXLINE * sizeof(char));
- char **errmsg = 0;
-
- sprintf(cmd,"SELECT Done, Type, Task FROM Tasks WHERE Type = '%s' OR Task = '%s' ORDER BY Type;",t.group, t.task);
- printf("TODO:");
- int err = sqlite3_exec(db,cmd,printcallback,0,errmsg);
- if (err) {
- fprintf(stderr, "Could not access db: %s\n", sqlite3_errmsg(db));
- sqlite3_close(db);
- exit(1);
- }
-
- free(cmd);
- return;
+int groupcallback(void *unused,int argc, char **argv, char **name){
+ strcpy(group,argv[0]);
+ return 0;
}
/* global variables */
int showdone = 0,
showall = 0;
+
char *group,
- *task;
+ *task,
+ *action;
int main(int argc, char *argv[]){
+ if (argc == 1) help();
+
sqlite3 *db;
- db = accessdb("odot.db");
- buildtables(db);
+ db = accessdb(filepath());
+ sqlcmd(db,BUILDTABLE);
- /* print all todo tasks if called alone */
- if (argc == 1) {
- print(db);
- return 0;
- }
group = malloc(MAXLINE * sizeof(char));
task = malloc(MAXLINE * sizeof(char));
+ action = malloc(MAXLINE * sizeof(char));
- char *action = malloc(100*sizeof(char));
-
- strcpy(action,argv[1]);
parseopt(argc,argv);
- struct task t = maketask(task,group);
- free(task);
- free(group);
-
-
- operate(action,t,db);
+ operate(db);
sqlite3_close(db);
return 0;
void parseopt(int n, char **args){
char c;
- while ((c = getopt(n,args,"g:ad")) != -1){
+ while ((c = getopt(n,args,"g:adh")) != -1){
switch (c) {
+ case 'h':
+ help();
+ break;
case 'a':
showall = 1;
break;
showdone = 1;
break;
case 'g':
- strcpy(group,optarg);
+ sprintf(group,"%s",optarg);
break;
case '?':
printf("Unknown Option: %c\n", optopt);
}
}
- if (strcmp(group, "") == 0) strcpy(group,"all");
+ sprintf(group,"%s",(strcmp(group,"") == 0) ? "" : group);
+ sprintf(action,"%s",args[optind]);
- for (; optind < n; optind++){
- if (optind > 1) {
- strcat(task,args[optind]);
- strcat(task,(optind != n -1) ? " " : "");
- }
+ for (int j = optind + 1; j < n; j++){
+ strcat(task,args[j]);
+ strcat(task,(j != n-1) ? " " : "");
}
}
-struct task maketask(char *task, char *group){
- struct task tmp;
+void operate(sqlite3 *db){
+ char *cmd = malloc(MAXLINE*sizeof(char));
- tmp.task = malloc(strlen(task)*sizeof(char));
- strcpy(tmp.task,task);
-
- tmp.group = malloc(strlen(group)*sizeof(char));
- strcpy(tmp.group,group);
-
- return tmp;
-}
-
-void operate(char *action, struct task t, sqlite3 *db){
if (strcmp(action,"new") == 0){
- addtask(db, t);
+ sprintf(cmd,"%s%s' ,'%s', 0);",INSERT,task,group);
+ sqlcmd(db,cmd);
} else if (strcmp(action,"done") == 0){
- donetask(db, t);
+ sprintf(cmd,"%s%s';",DONE,task);
+ sqlcmd(db,cmd);
+ sprintf(cmd,"%s%s';", GETGROUP,task);
+ sqlgroup(db,cmd);
+ sprintf(cmd,"SELECT Done, Task FROM Tasks WHERE Task = '%s'",task);
+ printf("\n");
+ sqlprint(db,cmd);
} else if (strcmp(action,"remove") == 0){
- removetask(db,t);
+ sprintf(cmd,"%s%s';",DELETE,task);
+ sqlcmd(db,cmd);
} else if (strcmp(action,"show") != 0) {
- printf("Unknown subcommand: %s\n",action);
+ fprintf(stderr,"\033[33;1mUnknown subcommand\033[0m: %s\n",action);
}
+ printf("\n\t\033[35;1mTODO\033[0m: \033[36m%s\033[0m\n\n",group);
if (showall == 1) {
if (showdone == 1) {
- printdone(db);
+ sqlprint(db,PRINTALL);
} else {
- print(db);
+ sqlprint(db,PRINT);
}
} else {
if (showdone == 1) {
- printgroupdone(db,t);
+ sprintf(cmd,"%s%s' ORDER BY Done;",PRINTGROUPALL,group);
+ sqlprint(db,cmd);
+ } else if (strcmp(group,"\t") != 0) {
+ sprintf(cmd,"%s%s';",PRINTGROUP,group);
+ sqlprint(db,cmd);
} else {
- printgroup(db,t);
+ sqlprint(db,PRINT);
}
}
}
+
+char *filepath(void){
+ char *dir = getenv("XDG_DATA_HOME");
+ char *db = malloc(MAXLINE * sizeof(char));
+
+ if (!dir) {
+ dir = getenv("HOME");
+ if (!dir) error(3);
+ strcat(dir,"/.local/share");
+ }
+ strcat(dir,"/odot");
+
+ DIR *test = opendir(dir);
+
+ if (test) {
+ closedir(test);
+ } else {
+ int err = mkdir(dir, 0777);
+ if (err) error(2);
+ }
+
+ sprintf(db,"%s/odot.db",dir);
+
+ return db;
+}
+
+void error(int err){
+ switch (err) {
+ case 1:
+ fprintf(stderr,"^^ SQL error ^^\n");
+ break;
+ case 2:
+ fprintf(stderr,"Could not create odot directory\n\t$XDG_DATA_HOME/odot\n");
+ break;
+ case 3:
+ fprintf(stderr,"Could not determine $HOME\n");
+ break;
+ }
+ exit(err);
+}
+
+void help(){
+ printf("Usage: odot [subcommand] (task)\n");
+ printf("\tSubcommands:\n");
+ printf("\tnew\tadd new task to database\n");
+ printf("\tdone\tmark task as done in database\n");
+ printf("\tshow\tshow tasks in database\n");
+ printf("\tremove\tremove task from database\t\n");
+ printf("\tOptions:\n");
+ printf("\t-a\tshow all groups\n");
+ printf("\t-d\talso show completed tasks\n");
+ printf("\t-g\tset group for task\n");
+ printf("\t-h\tshow this help\n");
+
+ exit(0);
+}
#include <unistd.h>
#include <time.h>
#include <math.h>
+#include <sys/stat.h>
+#include <dirent.h>
#include "sqlite3.h"
#define MAXLINE 10000
-struct task {
- char *task;
- char *group;
-};
+#define BUILDTABLE "CREATE TABLE IF NOT EXISTS Tasks (Task varchar(1000) NOT NULL PRIMARY KEY, Type varchar(8), Done int NOT NULL DEFAULT 0);"
+#define INSERT "INSERT INTO Tasks VALUES ( '"
+#define DELETE "DELETE FROM Tasks WHERE Task = '"
+#define DONE "UPDATE Tasks SET Done = 1 WHERE Task = '"
+#define GETGROUP "SELECT Type FROM Tasks WHERE Task = '"
+#define PRINT "SELECT Done, Type, Task FROM Tasks WHERE Done = 0 ORDER BY Type;"
+#define PRINTALL "SELECT Done, Type, Task FROM Tasks ORDER BY Type;"
+#define PRINTGROUP "SELECT Done, Task FROM Tasks WHERE Done = 0 AND Type = '"
+#define PRINTGROUPALL "SELECT Done, Task FROM Tasks WHERE Type = '"
+char *filepath(void);
+void error(int);
+void help(void);
void parseopt(int, char**);
-void operate(char *, struct task, sqlite3 *);
-struct task maketask(char *, char *);
+void operate(sqlite3 *);
/* functions for interfacing with database: database.c */
sqlite3 *accessdb(char *);
-void buildtables(sqlite3 *);
-void addtask(sqlite3 *, struct task);
-void removetask(sqlite3 *, struct task);
-void donetask(sqlite3 *, struct task);
+void sqlcmd(sqlite3 *,char *);
+void sqlprint(sqlite3 *,char *);
+void sqlgroup(sqlite3 *,char *);
+void sqlerror(sqlite3 *);
int printcallback(void *,int,char **,char **);
-void print(sqlite3 *);
-void printdone(sqlite3 *);
-void printgroup(sqlite3 *, struct task);
-void printgroupdone(sqlite3 *, struct task);
+int groupcallback(void *,int,char **,char **);