X-Git-Url: https://git.wpitchoune.net/gitweb/?a=blobdiff_plain;f=src%2Ftw.c;h=5ec2bc41ca7a435401c740839b968b88bff0f9c1;hb=f951f3835f81ff1deeef1e9d56e861db2c61924a;hp=366a0dc2f3377072a2959e0ce6f961b784689a3f;hpb=2b8e6f4abbedd42ca15b9e67a35ee63c7b290d84;p=ptask.git diff --git a/src/tw.c b/src/tw.c index 366a0dc..5ec2bc4 100644 --- a/src/tw.c +++ b/src/tw.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 jeanfi@gmail.com + * Copyright (C) 2012-2013 jeanfi@gmail.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -16,40 +16,59 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA */ +#define _GNU_SOURCE #include #include #include +#include +#include -#include +#include +#include +#include "note.h" +#include #include "tw.h" -char *task_exec(char *opts) +struct tm *parse_time(const char *t) +{ + struct tm *tm; + + tm = malloc(sizeof(struct tm)); + memset(tm, 0, sizeof(struct tm)); + strptime(t, "%Y%m%dT%H%M%S%Z", tm); + + return tm; +} + +static char *task_exec(char *opts) { FILE *f; - int ret, s; + int ret; + size_t s; char *str, *tmp, *cmd, buf[1024]; - str = NULL; + log_fct_enter(); - cmd = malloc(strlen("task rc.json.array=on ") + strlen(opts) + 1); - strcpy(cmd, "task rc.json.array=on "); + cmd = malloc(strlen("task ") + strlen(opts) + 1); + strcpy(cmd, "task "); strcat(cmd, opts); - printf("execute: %s\n", cmd); + log_debug("execute: %s", cmd); f = popen(cmd, "r"); + free(cmd); + if (!f) { perror("popen"); - goto exit_free; + return NULL; } - str = malloc(1); - str[0] = '\0'; + str = strdup(""); while ((s = fread(buf, 1, 1024, f))) { - tmp = malloc(strlen(str) + s + 1); + tmp = malloc(strlen(str) + s + (size_t)1); memcpy(tmp, str, strlen(str)); memcpy(tmp + strlen(str), buf, s); tmp[strlen(str) + s] = '\0'; @@ -59,40 +78,102 @@ char *task_exec(char *opts) ret = pclose(f); - if (ret == -1) { - printf("pclose fails\n"); - perror("pclose"); - } + if (ret == -1) + log_err("pclose fails"); - exit_free: - free(cmd); + log_fct_exit(); return str; } -static struct json_object *task_exec_json(char *opts) +static char *task_get_version() +{ + char *out; + + out = task_exec("--version"); + + trim(out); + + return out; +} + +static int task_check_version() +{ + char *ver; + + ver = task_get_version(); + + if (!ver) + return 0; + + log_debug("task version: %s", ver); + + if (!strcmp(ver, "2.2.0") || !strcmp(ver, "2.0.0")) + return 1; + else + return 0; +} + +static char *tw_exec(char *opts) +{ + char *opts2; + + if (!task_check_version()) { + log_err("ptask is not compatible with the installed version of" + " taskwarrior."); + return NULL; + } + + opts2 = malloc(strlen("rc.confirmation:no ") + + strlen(opts) + + 1); + strcpy(opts2, "rc.confirmation:no "); + strcat(opts2, opts); + + return task_exec(opts2); +} + +static struct json_object *task_exec_json(const char *opts) { struct json_object *o; - char *str; + char *str, *cmd; + + cmd = malloc(strlen("rc.json.array=on ") + strlen(opts) + 1); + strcpy(cmd, "rc.json.array=on "); + strcat(cmd, opts); - str = task_exec(opts); + str = tw_exec(cmd); if (str) { o = json_tokener_parse(str); free(str); - return o; + } else { + o = NULL; } - return NULL; + free(cmd); + + if (o && is_error(o)) + return NULL; + + return o; } -struct task **get_all_tasks() +struct task **tw_get_all_tasks(const char *status) { int i, n; struct json_object *jtasks, *jtask, *json; struct task **tasks; + char *opts; + const char *urg; + + opts = malloc(strlen("export status:") + strlen(status) + 1); - jtasks = task_exec_json("export"); + strcpy(opts, "export status:"); + strcat(opts, status); + + jtasks = task_exec_json(opts); + free(opts); if (!jtasks) return NULL; @@ -120,12 +201,43 @@ struct task **get_all_tasks() tasks[i]->project = strdup(json_object_get_string(json)); else - tasks[i]->project = NULL; + tasks[i]->project = strdup(""); + + json = json_object_object_get(jtask, "priority"); + if (json) + tasks[i]->priority + = strdup(json_object_get_string(json)); + else + tasks[i]->priority = strdup(""); json = json_object_object_get(jtask, "uuid"); tasks[i]->uuid = strdup(json_object_get_string(json)); - tasks[i]->note = NULL; + json = json_object_object_get(jtask, "urgency"); + urg = json_object_get_string(json); + if (urg) + tasks[i]->urgency = strdup(urg); + else + tasks[i]->urgency = NULL; + + tasks[i]->note = note_get(tasks[i]->uuid); + + json = json_object_object_get(jtask, "entry"); + tasks[i]->entry = parse_time(json_object_get_string(json)); + + json = json_object_object_get(jtask, "due"); + if (json) + tasks[i]->due + = parse_time(json_object_get_string(json)); + else + tasks[i]->due = NULL; + + json = json_object_object_get(jtask, "start"); + if (json) + tasks[i]->start + = parse_time(json_object_get_string(json)); + else + tasks[i]->start = NULL; } tasks[n] = NULL; @@ -135,7 +247,7 @@ struct task **get_all_tasks() return tasks; } -char *escape(const char *txt) +static char *escape(const char *txt) { char *result; char *c; @@ -143,19 +255,15 @@ char *escape(const char *txt) result = malloc(2*strlen(txt)+1); c = result; - while(*txt) { - switch(*txt) { + while (*txt) { + switch (*txt) { case '"': - *c = '\\'; c++; - *c = '"'; - break; case '$': - *c = '\\'; c++; - *c = '$'; - break; case '&': + case '<': + case '>': *c = '\\'; c++; - *c = '&'; + *c = *txt; break; default: *c = *txt; @@ -169,3 +277,314 @@ char *escape(const char *txt) return result; } +void tw_modify_description(const char *uuid, const char *newdesc) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" modify :\"") + + strlen(newdesc) + + strlen("\"") + + 1); + sprintf(opts, " %s modify \"%s\"", uuid, newdesc); + + tw_exec(opts); + + free(opts); +} + +void tw_modify_project(const char *uuid, const char *newproject) +{ + char *str; + char *opts; + + str = escape(newproject); + + opts = malloc(1 + + strlen(uuid) + + strlen(" modify project:\"") + + strlen(str) + + strlen("\"") + + 1); + sprintf(opts, " %s modify project:\"%s\"", uuid, str); + + tw_exec(opts); + + free(str); + free(opts); +} + +void tw_modify_priority(const char *uuid, const char *priority) +{ + char *str; + char *opts; + + log_fct_enter(); + + str = escape(priority); + + opts = malloc(1 + + strlen(uuid) + + strlen(" modify priority:\"") + + strlen(str) + + strlen("\"") + + 1); + sprintf(opts, " %s modify priority:\"%s\"", uuid, str); + + tw_exec(opts); + + free(str); + free(opts); + + log_fct_exit(); +} + +void tw_add(const char *newdesc, const char *prj, const char *prio) +{ + char *opts, *eprj; + + log_fct_enter(); + + eprj = escape(prj); + + opts = malloc(strlen("add") + + strlen(" priority:") + + 1 + + strlen(" project:\\\"") + + strlen(eprj) + + strlen("\\\"") + + strlen(" \"") + + strlen(newdesc) + + strlen("\"") + + 1); + + strcpy(opts, "add"); + + if (prio && strlen(prio) == 1) { + strcat(opts, " priority:"); + strcat(opts, prio); + } + + if (eprj && strlen(prj)) { + strcat(opts, " project:\\\""); + strcat(opts, eprj); + strcat(opts, "\\\""); + } + + strcat(opts, " \""); + strcat(opts, newdesc); + strcat(opts, "\""); + + tw_exec(opts); + + free(opts); + free(eprj); + + log_fct_exit(); +} + +void tw_task_done(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" done") + + 1); + sprintf(opts, " %s done", uuid); + + tw_exec(opts); + + free(opts); +} + +void tw_task_start(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" start") + + 1); + sprintf(opts, " %s start", uuid); + + tw_exec(opts); + + free(opts); +} + +void tw_task_stop(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" stop") + + 1); + sprintf(opts, " %s stop", uuid); + + tw_exec(opts); + + free(opts); +} + +void tw_task_remove(const char *uuid) +{ + char *opts; + + opts = malloc(1 + + strlen(uuid) + + strlen(" delete") + + 1); + sprintf(opts, " %s delete", uuid); + + tw_exec(opts); + + free(opts); +} + +static void task_free(struct task *task) +{ + if (!task) + return ; + + free(task->description); + free(task->status); + free(task->uuid); + free(task->note); + free(task->project); + free(task->priority); + free(task->urgency); + free(task->entry); + free(task->due); + free(task->start); + + free(task); +} + +void tw_task_list_free(struct task **tasks) +{ + struct task **cur; + + if (!tasks) + return ; + + for (cur = tasks; *cur; cur++) + task_free(*cur); + + free(tasks); +} + +static void project_free(struct project *p) +{ + if (!p) + return ; + + free(p->name); + free(p); +} + +void tw_project_list_free(struct project **prjs) +{ + struct project **cur; + + if (!prjs) + return ; + + for (cur = prjs; *cur; cur++) + project_free(*cur); + + free(prjs); +} + +static struct project *project_list_get(struct project **prjs, const char *name) +{ + struct project **cur; + + for (cur = prjs; *cur; cur++) + if (!strcmp((*cur)->name, name)) + return *cur; + + return NULL; +} + +static struct project *project_new(const char *name, int count) +{ + struct project *prj; + + prj = malloc(sizeof(struct project)); + + prj->name = strdup(name); + prj->count = count; + + return prj; +} + +static int projects_length(struct project **list) +{ + int n; + + if (!list) + return 0; + + n = 0; + while (*list) { + n++; + list++; + } + + return n; +} + +static struct project **projects_add(struct project **list, void *item) +{ + int n; + struct project **result; + + n = projects_length(list); + + result = (struct project **)malloc + ((n + 1 + 1) * sizeof(struct project *)); + + if (list) + memcpy(result, list, n * sizeof(struct project *)); + + result[n] = item; + result[n + 1] = NULL; + + return result; +} + +struct project **tw_get_projects(struct task **tasks) +{ + struct task **t_cur; + struct project **prjs, **tmp, *prj; + const char *prj_name; + + log_fct_enter(); + + prjs = malloc(2 * sizeof(struct project *)); + prjs[0] = project_new("ALL", 0); + prjs[1] = NULL; + + for (t_cur = tasks; *t_cur; t_cur++) { + prj_name = (*t_cur)->project; + prj = project_list_get(prjs, prj_name); + if (prj) { + prj->count++; + } else { + prj = project_new(prj_name, 1); + + tmp = projects_add(prjs, prj); + + free(prjs); + prjs = tmp; + } + prjs[0]->count++; + } + + log_fct_exit(); + + return prjs; +}