mirror of
https://github.com/michaeldv/pit.git
synced 2025-12-09 16:05:35 +00:00
More features
This commit is contained in:
39
src/action.c
Normal file
39
src/action.c
Normal file
@@ -0,0 +1,39 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
static void action_list()
|
||||
{
|
||||
PAction pa;
|
||||
PPager ppager;
|
||||
|
||||
pit_db_load();
|
||||
if (actions->number_of_records > 0) {
|
||||
ppager = pit_pager_initialize(PAGER_ACTION, actions->number_of_records);
|
||||
for_each_action(pa) {
|
||||
pit_pager_print(ppager, (uchar *)pa);
|
||||
}
|
||||
pit_pager_flush(ppager);
|
||||
}
|
||||
}
|
||||
|
||||
uchar *pit_action(ulong id, char *subject, char *message)
|
||||
{
|
||||
static Action action;
|
||||
|
||||
memset(&action, 0, sizeof(action));
|
||||
|
||||
action.subject_id = id;
|
||||
strncpy(action.subject, subject, sizeof(action.subject) - 1);
|
||||
strncpy(action.username, current_user(), sizeof(action.username) - 1);
|
||||
strncpy(action.message, message, sizeof(action.message) - 1);
|
||||
|
||||
return pit_table_insert(actions, (uchar *)&action);
|
||||
}
|
||||
|
||||
int pit_log(char *argv[])
|
||||
{
|
||||
action_list();
|
||||
return 1;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
ulong subject_id; /* Reference to the specific Project, Task, or Note. */
|
||||
char subject[16]; /* Project, Task, or Note. */
|
||||
char message[255]; /* Log message. */
|
||||
ulong created_by; /* Who added log message? */
|
||||
time_t created_at; /* When log message was added? */
|
||||
|
||||
PActivity pit_add_activity(ulong id, char *subject, char *message, ulong user_id) {
|
||||
static Activity activity;
|
||||
|
||||
memset(&activity, 0, sizeof(activity));
|
||||
|
||||
activity.subject_id = id;
|
||||
activity.created_by = user_id;
|
||||
activity.created_at = time(NULL);
|
||||
strncpy(activity.subject, subject, sizeof(activity.subject) - 1);
|
||||
strncpy(activity.message, message, sizeof(activity.message) - 1);
|
||||
|
||||
return &activity;
|
||||
}
|
||||
31
src/args.c
31
src/args.c
@@ -46,7 +46,7 @@ ulong pit_arg_number(char **arg, char *required)
|
||||
|
||||
// char *strptime(const char *restrict buf, const char *restrict format, struct tm *restrict tm);
|
||||
// time_t mktime ( struct tm * timeptr );
|
||||
time_t pit_arg_time(char **arg, char *required)
|
||||
time_t pit_arg_date(char **arg, char *required)
|
||||
{
|
||||
time_t seconds = (time_t)-1;
|
||||
struct tm tm;
|
||||
@@ -100,4 +100,31 @@ time_t pit_arg_time(char **arg, char *required)
|
||||
}
|
||||
|
||||
return seconds;
|
||||
}
|
||||
}
|
||||
|
||||
time_t pit_arg_time(char **arg, char *required)
|
||||
{
|
||||
time_t seconds = (time_t)-1;
|
||||
char *format;
|
||||
struct tm tm;
|
||||
|
||||
if (required && (!*arg || pit_arg_is_option(arg))) {
|
||||
die("missing %s", required);
|
||||
} else {
|
||||
memset(&tm, 0, sizeof(tm)); /* Suppored time formats are HH, HH:MM, and :MM */
|
||||
if (**arg == ':') {
|
||||
format = ":%M"; /* Minutes only */
|
||||
} else if (strchr(*arg, ':')) {
|
||||
format = "%H:%M"; /* Hours and minutes */
|
||||
} else {
|
||||
format = "%H"; /* Hours only */
|
||||
}
|
||||
if (strptime(*arg, format, &tm)) {
|
||||
seconds = mktime(&tm);
|
||||
} else {
|
||||
die("invalid time format: %s", *arg);
|
||||
}
|
||||
}
|
||||
|
||||
return seconds;
|
||||
}
|
||||
|
||||
55
src/db.c
55
src/db.c
@@ -18,6 +18,35 @@ static char *pit_file_name()
|
||||
return file_name;
|
||||
}
|
||||
|
||||
static void read_header(FILE *file)
|
||||
{
|
||||
Header hd;
|
||||
|
||||
if (fread(&hd, sizeof(hd), 1, file)) {
|
||||
if (hd.signature[0] != 0x50 || hd.signature[1] != 0x49 || hd.signature[2] != 0x54) {
|
||||
die("invalid pit file");
|
||||
}
|
||||
if (hd.schema_version != 0x01) {
|
||||
die("invalid pit file version");
|
||||
}
|
||||
} else {
|
||||
die("couldn't read header");
|
||||
}
|
||||
}
|
||||
|
||||
static void write_header(FILE *file)
|
||||
{
|
||||
Header hd;
|
||||
|
||||
hd.signature[0] = 0x50; hd.signature[1] = 0x49; hd.signature[2] = 0x54;
|
||||
hd.schema_version = 0x01;
|
||||
memset(&hd.reserved, 0, sizeof(hd.reserved));
|
||||
|
||||
if (!fwrite(&hd, sizeof(hd), 1, file)) {
|
||||
die("couldn't write header");
|
||||
}
|
||||
}
|
||||
|
||||
int pit_init(char *argv[]) {
|
||||
char **arg = &argv[1];
|
||||
char *file_name = pit_file_name();
|
||||
@@ -44,24 +73,22 @@ void pit_db_load() {
|
||||
if (!file) {
|
||||
perish(file_name);
|
||||
} else {
|
||||
projects = pit_table_load(file);
|
||||
tasks = pit_table_load(file);
|
||||
notes = pit_table_load(file);
|
||||
activities = pit_table_load(file);
|
||||
users = pit_table_load(file);
|
||||
read_header(file);
|
||||
projects = pit_table_load(file);
|
||||
tasks = pit_table_load(file);
|
||||
notes = pit_table_load(file);
|
||||
actions = pit_table_load(file);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
void pit_db_initialize() {
|
||||
projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
activities = pit_table_initialize(sizeof(Activity), TABLE_HAS_CREATED_AT);
|
||||
users = pit_table_initialize(sizeof(User), TABLE_HAS_ID);
|
||||
projects = pit_table_initialize(sizeof(Project), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
tasks = pit_table_initialize(sizeof(Task), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
notes = pit_table_initialize(sizeof(Note), TABLE_HAS_ID | TABLE_HAS_TIMESTAMPS);
|
||||
actions = pit_table_initialize(sizeof(Action), TABLE_HAS_CREATED_AT);
|
||||
|
||||
pit_table_insert(users, (uchar *)pit_current_user());
|
||||
pit_table_insert(activities, (uchar *)pit_add_activity(0, "", "Initialized pit", 1));
|
||||
pit_action(0, "pit", "Initialized pit");
|
||||
|
||||
pit_db_save();
|
||||
}
|
||||
@@ -73,11 +100,11 @@ void pit_db_save() {
|
||||
if (!file) {
|
||||
perish(file_name);
|
||||
} else {
|
||||
write_header(file);
|
||||
pit_table_save(file, projects);
|
||||
pit_table_save(file, tasks);
|
||||
pit_table_save(file, notes);
|
||||
pit_table_save(file, activities);
|
||||
pit_table_save(file, users);
|
||||
pit_table_save(file, actions);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
|
||||
37
src/object.h
37
src/object.h
@@ -1,16 +1,20 @@
|
||||
#if !defined(__MODELS_H__)
|
||||
#define __MODELS_H__
|
||||
|
||||
typedef struct _Header {
|
||||
char signature[3];
|
||||
char schema_version;
|
||||
char reserved[16];
|
||||
} Header, *PHeader;
|
||||
|
||||
typedef struct _Project {
|
||||
ulong id;
|
||||
char username[32]; /* User the project belongs to. */
|
||||
char name[128]; /* Project name. */
|
||||
char status[16]; /* Project status. */
|
||||
ulong number_of_open_tasks; /* Number of open tasks. */
|
||||
ulong number_of_closed_tasks; /* Number of closed tasks. */
|
||||
ulong closed_by; /* Who closed the project? */
|
||||
ulong number_of_tasks; /* Number of tasks for the project. */
|
||||
ulong created_by; /* Who created the project? */
|
||||
ulong updated_by; /* Who last updated the project? */
|
||||
time_t closed_at; /* When the project was closed? */
|
||||
time_t created_at; /* When the project was created? */
|
||||
time_t updated_at; /* When the project was last updated? */
|
||||
} Project, *PProject;
|
||||
@@ -18,15 +22,13 @@ typedef struct _Project {
|
||||
typedef struct _Task {
|
||||
ulong id;
|
||||
ulong project_id; /* Which project the task belongs to? */
|
||||
char username[32]; /* User the task belongs to. */
|
||||
char name[128]; /* Task name. */
|
||||
char status[16]; /* Task status. */
|
||||
char priority[16]; /* Task priority. */
|
||||
time_t deadline; /* Task deadline. */
|
||||
ulong number_of_notes; /* Number of notes. */
|
||||
ulong closed_by; /* Who closed the task? */
|
||||
ulong created_by; /* Who created the task? */
|
||||
ulong updated_by; /* Who last updated the task? */
|
||||
time_t closed_at; /* When the task was closed? */
|
||||
time_t date; /* Generic date/time, ex: task deadline. */
|
||||
time_t time; /* Generic time, ex: time spent on the task. */
|
||||
ulong number_of_notes; /* Number of notes for the task. */
|
||||
time_t created_at; /* When the task was created? */
|
||||
time_t updated_at; /* When the task was last updated? */
|
||||
} Task, *PTask;
|
||||
@@ -34,25 +36,18 @@ typedef struct _Task {
|
||||
typedef struct _Note {
|
||||
ulong id;
|
||||
ulong task_id; /* Task the note belongs to. */
|
||||
char username[32]; /* User the note belongs to. */
|
||||
char message[255]; /* The body of the note. */
|
||||
ulong created_by; /* Who created the note? */
|
||||
ulong updated_by; /* Who last updated the note? */
|
||||
time_t created_at; /* When the note was created? */
|
||||
time_t updated_at; /* When the note was last updated? */
|
||||
} Note, *PNote;
|
||||
|
||||
typedef struct _Activity {
|
||||
typedef struct _Action {
|
||||
ulong subject_id; /* Reference to the specific Project, Task, or Note. */
|
||||
char subject[16]; /* Project, Task, or Note. */
|
||||
char username[32]; /* Who added the log message? */
|
||||
char message[255]; /* Log message. */
|
||||
ulong created_by; /* Who added log message? */
|
||||
time_t created_at; /* When log message was added? */
|
||||
} Activity, *PActivity;
|
||||
|
||||
typedef struct _User {
|
||||
ulong id;
|
||||
char username[32]; /* Username. */
|
||||
char email[32]; /* User's email. */
|
||||
} User, *PUser;
|
||||
} Action, *PAction;
|
||||
|
||||
#endif
|
||||
|
||||
32
src/pager.c
32
src/pager.c
@@ -27,6 +27,7 @@ void pit_pager_print(PPager ppager, uchar *entry)
|
||||
case PAGER_TASK:
|
||||
sprintf(str, "%lu", ((PTask)*pentry)->id);
|
||||
ppager->max.task.id = max(ppager->max.task.id, strlen(str));
|
||||
ppager->max.task.username = max(ppager->max.task.username, strlen(((PTask)*pentry)->username));
|
||||
ppager->max.task.name = max(ppager->max.task.name, strlen(((PTask)*pentry)->name));
|
||||
ppager->max.task.status = max(ppager->max.task.status, strlen(((PTask)*pentry)->status));
|
||||
ppager->max.task.priority = max(ppager->max.task.priority, strlen(((PTask)*pentry)->priority));
|
||||
@@ -34,9 +35,14 @@ void pit_pager_print(PPager ppager, uchar *entry)
|
||||
case PAGER_PROJECT:
|
||||
sprintf(str, "%lu", ((PProject)*pentry)->id);
|
||||
ppager->max.project.id = max(ppager->max.project.id, strlen(str));
|
||||
ppager->max.project.username = max(ppager->max.project.username, strlen(((PProject)*pentry)->username));
|
||||
ppager->max.project.name = max(ppager->max.project.name, strlen(((PProject)*pentry)->name));
|
||||
ppager->max.project.status = max(ppager->max.project.status, strlen(((PProject)*pentry)->status));
|
||||
break;
|
||||
case PAGER_ACTION:
|
||||
ppager->max.action.username = max(ppager->max.action.username, strlen(((PAction)*pentry)->username));
|
||||
ppager->max.action.subject = max(ppager->max.action.subject, strlen(((PAction)*pentry)->subject));
|
||||
break;
|
||||
default:
|
||||
die("invalid pager type: %d\n", ppager->type);
|
||||
}
|
||||
@@ -46,17 +52,18 @@ void pit_pager_print(PPager ppager, uchar *entry)
|
||||
void pit_pager_flush(PPager ppager)
|
||||
{
|
||||
uchar **pentry;
|
||||
char format[64];
|
||||
char format[64], timestamp[32];
|
||||
|
||||
switch(ppager->type) {
|
||||
case PAGER_TASK:
|
||||
sprintf(format, "%%c %%%dlu: %%-%ds %%-%ds %%-%ds (%%lu note%%s)\n",
|
||||
ppager->max.task.id, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.name
|
||||
sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] [%%-%ds] %%-%ds (%%lu note%%s)\n",
|
||||
ppager->max.task.id, ppager->max.task.username, ppager->max.task.status, ppager->max.task.priority, ppager->max.task.name
|
||||
);
|
||||
for_each_entry(ppager, pentry) {
|
||||
printf(format,
|
||||
(((PTask)*pentry)->id == tasks->current ? '*' : ' '),
|
||||
((PTask)*pentry)->id,
|
||||
((PTask)*pentry)->username,
|
||||
((PTask)*pentry)->status,
|
||||
((PTask)*pentry)->priority,
|
||||
((PTask)*pentry)->name,
|
||||
@@ -66,21 +73,32 @@ void pit_pager_flush(PPager ppager)
|
||||
}
|
||||
break;
|
||||
case PAGER_PROJECT:
|
||||
sprintf(format, "%%c %%%dlu: %%-%ds %%-%ds (%%lu open, %%lu closed task%%s)\n",
|
||||
ppager->max.project.id, ppager->max.project.status, ppager->max.project.name
|
||||
sprintf(format, "%%c %%%dlu: (%%-%ds) [%%-%ds] %%-%ds (%%lu task%%s)\n",
|
||||
ppager->max.project.id, ppager->max.project.username, ppager->max.project.status, ppager->max.project.name
|
||||
);
|
||||
for_each_entry(ppager, pentry) {
|
||||
printf(format,
|
||||
(((PProject)*pentry)->id == projects->current ? '*' : ' '),
|
||||
((PProject)*pentry)->id,
|
||||
((PProject)*pentry)->username,
|
||||
((PProject)*pentry)->status,
|
||||
((PProject)*pentry)->name,
|
||||
((PProject)*pentry)->number_of_open_tasks,
|
||||
((PProject)*pentry)->number_of_closed_tasks,
|
||||
((PProject)*pentry)->number_of_tasks,
|
||||
(projects->number_of_records != 1 ? "s" : "")
|
||||
);
|
||||
}
|
||||
break;
|
||||
case PAGER_ACTION:
|
||||
sprintf(format, "%%s (%%-%ds): %%s\n", ppager->max.action.username);
|
||||
for_each_entry(ppager, pentry) {
|
||||
strftime(timestamp, sizeof(timestamp), "%b %d, %Y %H:%M", localtime(&((PAction)*pentry)->created_at));
|
||||
printf(format,
|
||||
timestamp,
|
||||
((PAction)*pentry)->username,
|
||||
((PAction)*pentry)->message
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pit_pager_free(ppager);
|
||||
die("invalid pager type: %d\n", ppager->type);
|
||||
|
||||
18
src/pager.h
18
src/pager.h
@@ -1,11 +1,10 @@
|
||||
#if !defined(__PAGER_H__)
|
||||
#define __PAGER_H__
|
||||
|
||||
#define PAGER_ACTIVITY 1
|
||||
#define PAGER_PROJECT 2
|
||||
#define PAGER_TASK 4
|
||||
#define PAGER_NOTE 8
|
||||
#define PAGER_USER 16
|
||||
#define PAGER_ACTION 1
|
||||
#define PAGER_PROJECT 2
|
||||
#define PAGER_TASK 4
|
||||
#define PAGER_NOTE 8
|
||||
|
||||
typedef struct _Pager {
|
||||
ulong type;
|
||||
@@ -14,16 +13,23 @@ typedef struct _Pager {
|
||||
union {
|
||||
struct {
|
||||
int id;
|
||||
int username;
|
||||
int name;
|
||||
int status;
|
||||
} project;
|
||||
struct {
|
||||
int id;
|
||||
int username;
|
||||
int name;
|
||||
int status;
|
||||
int priority;
|
||||
int deadline;
|
||||
int date;
|
||||
int time;
|
||||
} task;
|
||||
struct {
|
||||
int username;
|
||||
int subject;
|
||||
} action;
|
||||
} max;
|
||||
} Pager, *PPager;
|
||||
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
PTable projects;
|
||||
PTable tasks;
|
||||
PTable notes;
|
||||
PTable activities;
|
||||
PTable users;
|
||||
PTable actions;
|
||||
|
||||
static int usage() {
|
||||
printf("usage...\n");
|
||||
@@ -62,7 +61,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (strstr(commands[2], argv[1]) == commands[2]) {
|
||||
return 1; /* pit_note(&argv[1]); */
|
||||
} else if (strstr(commands[3], argv[1]) == commands[3]) {
|
||||
return 1; /* pit_log(&argv[1]); */
|
||||
return pit_log(&argv[1]);
|
||||
} else if (strstr(commands[4], argv[1]) == commands[4]) {
|
||||
return pit_init(&argv[1]);
|
||||
}
|
||||
|
||||
30
src/pit.h
30
src/pit.h
@@ -28,24 +28,23 @@ typedef int bool;
|
||||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#define for_each_activity(ptr) for (ptr = (PActivity)activities->slots; (ptr - (PActivity)activities->slots) < activities->number_of_records; ptr++)
|
||||
#define for_each_project(ptr) for (ptr = (PProject)projects->slots; (ptr - (PProject)projects->slots) < projects->number_of_records; ptr++)
|
||||
#define for_each_note(ptr) for (ptr = (PNote)notes->slots; (ptr - (PNote)notes->slots) < notes->number_of_records; ptr++)
|
||||
#define for_each_task(ptr) for (ptr = (PTask)tasks->slots; (ptr - (PTask)tasks->slots) < tasks->number_of_records; ptr++)
|
||||
#define for_each_user(ptr) for (ptr = (PUser)users->slots; (ptr - (PUser)users->slots) < users->number_of_records; ptr++)
|
||||
#define for_each_project(ptr) for (ptr = (PProject)projects->slots; (ptr - (PProject)projects->slots) < projects->number_of_records; ptr++)
|
||||
#define for_each_task(ptr) for (ptr = (PTask)tasks->slots; (ptr - (PTask)tasks->slots) < tasks->number_of_records; ptr++)
|
||||
#define for_each_note(ptr) for (ptr = (PNote)notes->slots; (ptr - (PNote)notes->slots) < notes->number_of_records; ptr++)
|
||||
#define for_each_action(ptr) for (ptr = (PAction)actions->slots; (ptr - (PAction)actions->slots) < actions->number_of_records; ptr++)
|
||||
|
||||
/* Externals. */
|
||||
extern PTable activities;
|
||||
extern PTable actions;
|
||||
extern PTable notes;
|
||||
extern PTable projects;
|
||||
extern PTable tasks;
|
||||
extern PTable users;
|
||||
|
||||
/* args.c */
|
||||
int pit_arg_is_option(char **arg);
|
||||
int pit_arg_option(char **arg);
|
||||
char *pit_arg_string(char **arg, char *required);
|
||||
ulong pit_arg_number(char **arg, char *required);
|
||||
time_t pit_arg_date(char **arg, char *required);
|
||||
time_t pit_arg_time(char **arg, char *required);
|
||||
|
||||
/* db.c */
|
||||
@@ -54,18 +53,19 @@ void pit_db_load();
|
||||
void pit_db_save();
|
||||
void pit_db_initialize();
|
||||
|
||||
/* activity.c project.c task.c user.c */
|
||||
int pit_project(char *argv[]);
|
||||
int pit_task(char *argv[]);
|
||||
char *pit_current_user();
|
||||
PActivity pit_add_activity(ulong id, char *subject, char *message, ulong user_id);
|
||||
/* log.c project.c task.c user.c */
|
||||
int pit_project(char *argv[]);
|
||||
int pit_task(char *argv[]);
|
||||
int pit_log(char *argv[]);
|
||||
char *pit_current_user();
|
||||
uchar *pit_action(ulong id, char *subject, char *message);
|
||||
|
||||
/* util.c */
|
||||
void die(char *msg, ...);
|
||||
void perish(char *prefix);
|
||||
void die(char *msg, ...);
|
||||
void perish(char *prefix);
|
||||
char *mem2str(char *mem, int len);
|
||||
char *current_user();
|
||||
char *home_dir(char *username, int len);
|
||||
char *expand_path(char *path, char *expanded);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,19 +42,13 @@ static void create_project(char *name, char *status)
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
|
||||
if (!status) {
|
||||
status = "active";
|
||||
}
|
||||
if (!status) status = "active";
|
||||
printf("creating project [%s], status [%s]\n", name, status);
|
||||
|
||||
strncpy(p.name, name, sizeof(p.name) - 1);
|
||||
strncpy(p.status, status, sizeof(p.status) - 1);
|
||||
p.number_of_open_tasks = 0;
|
||||
p.number_of_closed_tasks = 0;
|
||||
p.closed_by = 0;
|
||||
p.created_by = p.updated_by = 1; // TODO
|
||||
p.closed_at = 0;
|
||||
p.created_at = p.updated_at = time(NULL);
|
||||
strncpy(p.username, current_user(), sizeof(p.username) - 1);
|
||||
|
||||
pp = (PProject)pit_table_insert(projects, (uchar *)&p);
|
||||
pit_table_mark(projects, pp->id);
|
||||
pit_db_save();
|
||||
@@ -68,18 +62,13 @@ static int show_project(ulong number)
|
||||
pit_db_load();
|
||||
pp = (PProject)pit_table_find(projects, number);
|
||||
if (pp) {
|
||||
printf("%lu: %s (%s, %lu open task%s, %lu closed task%s)\n",
|
||||
pp->id, pp->name, pp->status,
|
||||
pp->number_of_open_tasks, (pp->number_of_open_tasks != 1 ? "s" : ""),
|
||||
pp->number_of_closed_tasks, (pp->number_of_closed_tasks != 1 ? "s" : ""));
|
||||
if (pp->number_of_open_tasks > 0) {
|
||||
printf("%lu: %s (%s, %lu task%s)\n",
|
||||
pp->id, pp->name, pp->status, pp->number_of_tasks, (pp->number_of_tasks != 1 ? "s" : ""));
|
||||
if (pp->number_of_tasks > 0) {
|
||||
PTask pt = (PTask)tasks->slots;
|
||||
|
||||
puts("Open tasks:");
|
||||
puts("Tasks:");
|
||||
for_each_task(pt) {
|
||||
if (pt->closed_at) {
|
||||
continue;
|
||||
}
|
||||
printf(" %c %lu: %s (%lu notes)\n", (pt->id == tasks->current ? '*' : ' '), pt->id, pt->name, pt->number_of_notes);
|
||||
}
|
||||
}
|
||||
|
||||
92
src/task.c
92
src/task.c
@@ -1,21 +1,23 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "pit.h"
|
||||
|
||||
static void task_list(char *name, char *status, char *priority, time_t deadline);
|
||||
static void task_create(char *name, char *status, char *priority, time_t deadline);
|
||||
static void task_list(char *name, char *status, char *priority, time_t date, time_t time);
|
||||
static void task_create(char *name, char *status, char *priority, time_t date, time_t time);
|
||||
static void task_show(ulong number);
|
||||
static void task_delete(ulong number);
|
||||
static void task_update(ulong number, char *name, char *status, char *priority, time_t deadline);
|
||||
static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *deadline);
|
||||
static void task_update(ulong number, char *name, char *status, char *priority, time_t date, time_t time);
|
||||
static void task_log(char *message, ulong id, ...);
|
||||
static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *date, time_t *time);
|
||||
|
||||
/*
|
||||
** CREATING TASKS:
|
||||
** pit task -c name [-s status] [-d deadline] [-p priority]
|
||||
** pit task -c name [-s status] [-p priority] [-d date] [-t time]
|
||||
**
|
||||
** UPDATING TASKS:
|
||||
** pit task -u [number] [-n name] [-s status] [-d deadline] [-p priority]
|
||||
** pit task -u [number] [-n name] [-s status] [-p priority] [-d date] [-t time]
|
||||
**
|
||||
** DELETING TASKS:
|
||||
** pit task -d [number]
|
||||
@@ -24,10 +26,10 @@ static void task_parse_options(char **arg, char **name, char **status, char **pr
|
||||
** pit task [[-q] number]
|
||||
**
|
||||
** LISTING TASKS:
|
||||
** pit task -q [-s status] [-d deadline] [-p priority]
|
||||
** pit task -q [-s status] [-p priority] [-d date] [-t time]
|
||||
*/
|
||||
|
||||
static void task_list(char *name, char *status, char *priority, time_t deadline)
|
||||
static void task_list(char *name, char *status, char *priority, time_t date, time_t time)
|
||||
{
|
||||
PProject pp;
|
||||
PTask pt;
|
||||
@@ -47,7 +49,7 @@ static void task_list(char *name, char *status, char *priority, time_t deadline)
|
||||
}
|
||||
}
|
||||
|
||||
static void task_create(char *name, char *status, char *priority, time_t deadline)
|
||||
static void task_create(char *name, char *status, char *priority, time_t date, time_t time)
|
||||
{
|
||||
pit_db_load();
|
||||
|
||||
@@ -60,29 +62,24 @@ static void task_create(char *name, char *status, char *priority, time_t deadlin
|
||||
|
||||
memset(&t, 0, sizeof(t));
|
||||
|
||||
if (!status) {
|
||||
status = "open";
|
||||
}
|
||||
if (!priority) {
|
||||
priority = "normal";
|
||||
}
|
||||
if (!status) status = "open";
|
||||
if (!priority) priority = "normal";
|
||||
|
||||
printf("creating task: %s, status: %s, priority: %s, deadline: %s", name, status, priority, ctime(&deadline));
|
||||
printf("creating task: %s, status: %s, priority: %s, date: %s", name, status, priority, ctime(&date));
|
||||
|
||||
strncpy(t.name, name, sizeof(t.name) - 1);
|
||||
strncpy(t.status, status, sizeof(t.status) - 1);
|
||||
strncpy(t.priority, priority, sizeof(t.priority) - 1);
|
||||
strncpy(t.username, current_user(), sizeof(t.username) - 1);
|
||||
t.project_id = pp->id;
|
||||
t.deadline = deadline;
|
||||
t.number_of_notes = 0;
|
||||
t.closed_by = 0;
|
||||
t.created_by = t.updated_by = 1; // TODO
|
||||
t.closed_at = 0;
|
||||
t.created_at = t.updated_at = time(NULL);
|
||||
t.date = date;
|
||||
t.time = 0; /* TODO */
|
||||
|
||||
pt = (PTask)pit_table_insert(tasks, (uchar *)&t);
|
||||
pit_table_mark(tasks, pt->id);
|
||||
pp->number_of_open_tasks++;
|
||||
pp->number_of_tasks++;
|
||||
// pit_action(pit->id, "task", "created task #%d: %s (status: %s, priority: %s, date: %s)", pt->id, name, status, priority, (date ? ctime(&date) : "n/a"));
|
||||
task_log("created task #%d: %s (status: %s, priority: %s, date: %s)", pt->id, name, status, priority, (date ? ctime(&date) : "n/a"));
|
||||
pit_db_save();
|
||||
}
|
||||
}
|
||||
@@ -97,12 +94,23 @@ static void task_delete(ulong number)
|
||||
printf("task_delete(%lu)\n", number);
|
||||
}
|
||||
|
||||
static void task_update(ulong number, char *name, char *status, char *priority, time_t deadline)
|
||||
static void task_update(ulong number, char *name, char *status, char *priority, time_t date, time_t time)
|
||||
{
|
||||
printf("task_update: #%lu, name: %s, status: %s, priority: %s, deadline: %s", number, name, status, priority, ctime(&deadline));
|
||||
printf("task_update: #%lu, name: %s, status: %s, priority: %s, date: %s", number, name, status, priority, ctime(&date));
|
||||
}
|
||||
|
||||
static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *deadline)
|
||||
static void task_log(char *message, ulong id, ...)
|
||||
{
|
||||
char str[128];
|
||||
va_list params;
|
||||
|
||||
va_start(params, id);
|
||||
vsnprintf(str, sizeof(str), (char *)&id, params);
|
||||
pit_action(id, "task", str);
|
||||
va_end(params);
|
||||
}
|
||||
|
||||
static void task_parse_options(char **arg, char **name, char **status, char **priority, time_t *date, time_t *time)
|
||||
{
|
||||
while(*++arg) {
|
||||
switch(pit_arg_option(arg)) {
|
||||
@@ -113,7 +121,10 @@ static void task_parse_options(char **arg, char **name, char **status, char **pr
|
||||
*priority = pit_arg_string(++arg, "task priority");
|
||||
break;
|
||||
case 'd':
|
||||
*deadline = pit_arg_time(++arg, "task deadline");
|
||||
*date = pit_arg_date(++arg, "task date");
|
||||
break;
|
||||
case 't':
|
||||
*time = pit_arg_time(++arg, "task time");
|
||||
break;
|
||||
case 'n':
|
||||
if (name) {
|
||||
@@ -130,46 +141,47 @@ int pit_task(char *argv[])
|
||||
{
|
||||
char **arg = &argv[1];
|
||||
char *name = NULL, *status = NULL, *priority = NULL;
|
||||
time_t deadline = (time_t)0;
|
||||
time_t date = (time_t)0;
|
||||
time_t time = (time_t)0;
|
||||
ulong number = 0L;
|
||||
|
||||
if (!*arg) {
|
||||
task_list(NULL, NULL, NULL, 0); /* List all tasks (with default paramaters). */
|
||||
task_list(NULL, NULL, NULL, 0, 0); /* List all tasks (with default paramaters). */
|
||||
} else { /* pit task [number] */
|
||||
number = pit_arg_number(arg, NULL);
|
||||
if (number) {
|
||||
task_show(number);
|
||||
} else {
|
||||
switch(pit_arg_option(arg)) {
|
||||
case 'c': /* pit task -c name [-s status] [-p priority] [-d deadline] */
|
||||
case 'c': /* pit task -c name [-s status] [-p priority] [-d date] [-t time] */
|
||||
name = pit_arg_string(++arg, "task name");
|
||||
task_parse_options(arg, NULL, &status, &priority, &deadline);
|
||||
task_create(name, status, priority, deadline);
|
||||
task_parse_options(arg, NULL, &status, &priority, &date, &time);
|
||||
task_create(name, status, priority, date, time);
|
||||
break;
|
||||
case 'u': /* pit task -u [number] [-n name] [-s status] [-d deadline] [-p priority] */
|
||||
case 'u': /* pit task -u [number] [-n name] [-s status] [-p priority] [-d date] [-t time]*/
|
||||
number = pit_arg_number(++arg, NULL);
|
||||
if (!number) --arg;
|
||||
task_parse_options(arg, &name, &status, &priority, &deadline);
|
||||
if (!name && !status && !priority && !deadline) {
|
||||
task_parse_options(arg, &name, &status, &priority, &date, &time);
|
||||
if (!name && !status && !priority && !date && !time) {
|
||||
die("nothing to update");
|
||||
} else {
|
||||
task_update(number, name, status, priority, deadline);
|
||||
task_update(number, name, status, priority, date, time);
|
||||
}
|
||||
break;
|
||||
case 'd': /* pit task -d [number] */
|
||||
number = pit_arg_number(++arg, NULL);
|
||||
task_delete(number);
|
||||
break;
|
||||
case 'q': /* pit task -q [number | [-n name] [-s status] [-d deadline] [-p priority]] */
|
||||
case 'q': /* pit task -q [number | [-n name] [-s status] [-p priority] [-d date] [-t time]] */
|
||||
number = pit_arg_number(++arg, NULL);
|
||||
if (number) {
|
||||
task_show(number);
|
||||
} else {
|
||||
task_parse_options(--arg, &name, &status, &priority, &deadline);
|
||||
if (!name && !status && !priority && !deadline) {
|
||||
task_parse_options(--arg, &name, &status, &priority, &date, &time);
|
||||
if (!name && !status && !priority && !date && !time) {
|
||||
task_show(0);
|
||||
} else {
|
||||
task_list(name, status, priority, deadline);
|
||||
task_list(name, status, priority, date, time);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "pit.h"
|
||||
|
||||
char *pit_current_user() {
|
||||
return getlogin();
|
||||
}
|
||||
22
src/util.c
22
src/util.c
@@ -14,6 +14,20 @@ char *mem2str(char *mem, int len) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char *current_user() {
|
||||
static char *username = NULL;
|
||||
|
||||
if (!username) {
|
||||
struct passwd *pws = getpwuid(geteuid());
|
||||
if (!pws) {
|
||||
perish("no username?!");
|
||||
} else {
|
||||
username = pws->pw_name;
|
||||
}
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
char *home_dir(char *username, int len) {
|
||||
char *str = mem2str(username, len);
|
||||
struct passwd *pw = getpwnam(str);
|
||||
@@ -47,3 +61,11 @@ char *expand_path(char *path, char *expanded) {
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("your username: %s\n", current_user());
|
||||
printf("your (cached) username: %s\n", current_user());
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user