diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 5a1adc1..e54e6c6 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -1,4 +1,6 @@ add_executable(klist main.c process.c) target_include_directories(klist PRIVATE include) target_link_libraries(klist libklist) -target_compile_options(klist PRIVATE -Werror -Wall) #-Wextra) \ No newline at end of file +target_compile_options(klist PRIVATE -Werror -Wall) #-Wextra) + +add_test(NAME klist_userCreation COMMAND klist user -c) \ No newline at end of file diff --git a/src/cli/main.c b/src/cli/main.c index 2d14d09..59b8275 100644 --- a/src/cli/main.c +++ b/src/cli/main.c @@ -19,8 +19,6 @@ int main(int argc, char **argv) { if (!ctx->error) { setup(ctx, argc, argv); - klist_user *user = klist_user_get_by_local(ctx, getuid()); - klist_list *list = NULL; switch (ctx->cmd) { case USER: klist_user_context *user_ctx = ctx->cmd_ctx; @@ -75,10 +73,6 @@ int main(int argc, char **argv) { klist_task_context_deinit(task_ctx); default:; } - if (list) - klist_list_deinit(list); - if (user) - klist_user_deinit(user); } const int error = ctx->error; @@ -171,15 +165,11 @@ void setup(klist *ctx, int argc, char **argv) { } break; case TASK: - if (argc < 3) { - klist_print(ctx, KLIST_LOG_ERROR, "Prints all lists.\n"); - break; - } klist_task_context *task_ctx = klist_task_context_init(ctx); optind = 2; - while ((opt = getopt(argc, argv, "aedl:n:s:")) != -1) + while ((opt = getopt(argc, argv, "aedgl:n:s:")) != -1) switch (opt) { /*case 'a': task_ctx->cmd = TASK_ADD; @@ -190,6 +180,9 @@ void setup(klist *ctx, int argc, char **argv) { case 'd': task_ctx->cmd = TASK_DELETE; break; + case 'g': + task_ctx->cmd = TASK_GET; + break; case 'l': task_ctx->list = strdup(optarg); break; @@ -209,9 +202,6 @@ void setup(klist *ctx, int argc, char **argv) { "-d\tdelete a task" "Not providing a parameter prints all tasks of a list."); } - - if (task_ctx->cmd != TASK_DELETE) - task_ctx->cmd = TASK_ADD; ctx->cmd_ctx = task_ctx; break; default: diff --git a/src/cli/process.c b/src/cli/process.c index 7865585..1b09f27 100644 --- a/src/cli/process.c +++ b/src/cli/process.c @@ -116,6 +116,11 @@ int klist_app_list_delete(klist *ctx) { klist_list_context *list_ctx = ctx->cmd_ctx; klist_assure_user(ctx, getuid(), getlogin()); klist_user *user = klist_user_get_by_local(ctx, getuid()); + if (!user) { + klist_print(ctx, KLIST_LOG_ERROR, "User doesn't exist.\n"); + return 1; + } + klist_list *list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); @@ -137,10 +142,15 @@ int klist_app_task_add(klist *ctx) { return klist_app_task_edit(ctx); } int klist_app_task_edit(klist *ctx) { klist_task_context *task_ctx = ctx->cmd_ctx; + klist_assure_user(ctx, getuid(), getlogin()); klist_user *user = klist_user_get_by_local(ctx, getuid()); klist_list *list = NULL; - klist_assure_user(ctx, getuid(), getlogin()); + if (!user) { + klist_print(ctx, KLIST_LOG_ERROR, "User doesn't exist.\n"); + return 1; + } + list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); if (list) { size_t stages_len = 0; @@ -153,7 +163,6 @@ int klist_app_task_edit(klist *ctx) { for (; i < stages_len; i++) fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); fprintf(ctx->log_target, "\n"); - return 1; } int i = 0; ssize_t stage_id = -1; @@ -164,7 +173,7 @@ int klist_app_task_edit(klist *ctx) { if (stage_id == -1) { klist_print(ctx, KLIST_LOG_ERROR, "Stage %s not found. Use one of: ", task_ctx->stage); - int i = 0; + i = 0; for (; i < stages_len; i++) fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); fprintf(ctx->log_target, "\n"); @@ -173,8 +182,6 @@ int klist_app_task_edit(klist *ctx) { for (; i < stages_len; i++) klist_stage_deinit(stages[i]); free(stages); - if (ctx->error) - return ctx->error; klist_task *task = klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); @@ -192,6 +199,9 @@ int klist_app_task_edit(klist *ctx) { klist_task_deinit(task); } else klist_print(ctx, KLIST_LOG_ERROR, "List not found.\n"); + klist_user_deinit(user); + if (list) + klist_list_deinit(list); return 0; } @@ -199,6 +209,10 @@ int klist_app_task_get(klist *ctx) { klist_task_context *task_ctx = ctx->cmd_ctx; klist_assure_user(ctx, getuid(), getlogin()); klist_user *user = klist_user_get_by_local(ctx, getuid()); + if (!user) { + klist_print(ctx, KLIST_LOG_ERROR, "User doesn't exist.\n"); + return 1; + } klist_list *list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); if (list) { @@ -217,18 +231,12 @@ int klist_app_task_get(klist *ctx) { } else { size_t tasks_len = 0; klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); + klist_print_list(ctx, list, tasks, tasks_len); + int i = 0; - for (; i < tasks_len; i++) { - printf("Name: %s\n", (char *)tasks[i]->name); - printf("Description: %s\n", - tasks[i]->desc ? (char *)tasks[i]->desc : "N/A"); - klist_stage *stage = klist_stage_get_by_id(ctx, tasks[i]->stage_id); - printf("Stage: %s\n", (char *)stage->name); - klist_stage_deinit(stage); - klist_task_deinit(tasks[i]); - if ((i + 1) < tasks_len) - fprintf(ctx->log_target, "\n"); - } + for (; i < tasks_len; i++) + free(tasks[i]); + free(tasks); } } else klist_print(ctx, KLIST_LOG_ERROR, "list not found\n"); @@ -239,6 +247,10 @@ int klist_app_task_delete(klist *ctx) { klist_task_context *task_ctx = ctx->cmd_ctx; klist_assure_user(ctx, getuid(), getlogin()); klist_user *user = klist_user_get_by_local(ctx, getuid()); + if (!user) { + klist_print(ctx, KLIST_LOG_ERROR, "User doesn't exist.\n"); + return 1; + } klist_list *list = klist_list_get_by_user_and_name(ctx, user->id, task_ctx->list); if (list) { diff --git a/src/libklist/include/models.h b/src/libklist/include/models.h index 6545033..9afd36a 100644 --- a/src/libklist/include/models.h +++ b/src/libklist/include/models.h @@ -73,6 +73,6 @@ void klist_task_save(const klist *, klist_task *); void klist_task_delete(const klist *, const klist_task *); void klist_task_deinit(klist_task *); -void klist_print_user(klist *, klist_user *); -void klist_print_list(klist *, klist_list *); -void klist_print_task(klist *, klist_task *); \ No newline at end of file +void klist_print_user(klist *, const klist_user *); +void klist_print_list(klist *, klist_list *, klist_task **, size_t); +void klist_print_task(klist *, klist_task **, size_t); \ No newline at end of file diff --git a/src/libklist/models.c b/src/libklist/models.c index 892303f..6443d5e 100644 --- a/src/libklist/models.c +++ b/src/libklist/models.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "klist.h" #include "sql.h" @@ -366,3 +368,128 @@ void klist_task_deinit(klist_task *task) { free(task->desc); free(task); } + +/* + * printing + */ + +void repeat(size_t len, const char *sign) { + int i = 0; + for (; i < len; i++) + printf(sign); +} + +size_t longest_str(char **strings, size_t strings_len) { + size_t len = 0, i = 0; + for (; i < strings_len; i++) + if (strlen(strings[i]) > len) + len = strlen(strings[i]); + return len; +} + +void klist_print_user(klist *ctx, const klist_user *user) { + printf("" + "Name: %s\n" + "has local account: %s\n", + (char *)user->name, user->local_id > 0 ? "yes" : "no"); +} + +void print_table_line(char *left, size_t cols, char *filler, size_t col_width, + char *col_delim, char *right) { + printf("%s", left); + int i = 0; + for (i = 0; i < cols; i++) { + int j = 0; + for (; j < col_width; j++) + printf("%s", filler); + if (i + 1 != cols) + printf("%s", col_delim); + } + printf("%s\n", right); +} + +void klist_print_list(klist *ctx, klist_list *list, klist_task **tasks, + size_t count) { + struct winsize w; + int i = 0; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + int width = w.ws_col > 0 ? w.ws_col : 80; + + size_t stages_len = 0; + klist_stage **stages = + klist_stage_get_all_for_list(ctx, list->id, &stages_len); + + size_t stage_col_width = (width - 2 - (stages_len - 1)) / stages_len; + + int max_stages_id = 0; + for (i = 0; i < stages_len; i++) + if (stages[i]->id > max_stages_id) + max_stages_id = stages[i]->id + 1; + + int tasks_count_per_stage[max_stages_id]; + for (i = 0; i < max_stages_id; i++) + tasks_count_per_stage[i] = 0; + + for (i = 0; i < count; i++) + tasks_count_per_stage[tasks[i]->stage_id]++; + + int tasks_max = 0; + for (i = 0; i < max_stages_id; i++) + if (tasks_count_per_stage[i] > tasks_max) + tasks_max = tasks_count_per_stage[i]; + + print_table_line("╭", stages_len, "─", stage_col_width, "─", "╮"); + + // list name + printf("│"); + printf(" %s", (char *)list->name); + for (i = 0; i < width - 4 - strlen((char *)list->name); i++) + printf(" "); + printf("│\n"); + + print_table_line("├", stages_len, "─", stage_col_width, "┬", "┤"); + + printf("│"); + for (i = 0; i < stages_len; i++) { + int j = 0; + printf(" %s", (char *)stages[i]->name); + for (; j < stage_col_width - (strlen((char *)stages[i]->name) + 1); j++) + printf(" "); + if (i + 1 != stages_len) + printf("│"); + } + printf("│\n"); + + print_table_line("├", stages_len, "─", stage_col_width, "┼", "┤"); + + int stages_idx[max_stages_id]; + for (i = 0; i < max_stages_id; i++) + stages_idx[i] = 0; + for (i = 0; i < tasks_max; i++) { + printf("│"); + int j = 0; + for (; j < stages_len; j++) { + int k = stages_idx[stages[j]->id]; + u_long printed = 0; + for (; k < count; k++) + if (tasks[k]->stage_id == stages[j]->id) { + printf(" %s", (char *)tasks[k]->name); + printed = strlen((char *)tasks[k]->name) + 1; + stages_idx[stages[j]->id] = k + 1; + break; + } + int l = 0; + for (; l < stage_col_width - printed; l++) + printf(" "); + if (j + 1 != stages_len) + printf("│"); + } + printf("│\n"); + } + + print_table_line("╰", stages_len, "─", stage_col_width, "┴", "╯"); + + for (i = 0; i < stages_len; i++) + free(stages[i]); + free(stages); +}