From 363372f34e85599bce4768f4549a264946cb0650 Mon Sep 17 00:00:00 2001 From: Patrick Lipka Date: Fri, 10 Dec 2021 11:09:03 +0100 Subject: [PATCH] Basic UI implemented usinf GNU readline --- Makefile | 3 ++- src/track.cpp | 13 ++++++++-- src/track.h | 1 + src/tt.cpp | 27 ++++++++++++++++++++ src/ui.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ui.h | 15 +++++++++++ 6 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 src/ui.cpp create mode 100644 src/ui.h diff --git a/Makefile b/Makefile index 99a47f3..4dcf08b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ CXX ?= g++ CXXFLAGS := -g -Wall -pedantic OBJFLAGS := $(CXXFLAGS) -c +LDFLAGS := -lreadline BIN_PATH := bin SRC_PATH := src @@ -11,7 +12,7 @@ OBJ := $(addprefix $(SRC_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC))))) default: makedir all $(BIN_PATH)/tt: $(OBJ) - $(CXX) $(CXXFLAGS) -o $@ $(OBJ) + $(CXX) $(CXXFLAGS) -o $@ $(OBJ) $(LDFLAGS) $(SRC_PATH)/%.o: $(SRC_PATH)/%.cpp $(CXX) $(OBJFLAGS) -o $@ $< diff --git a/src/track.cpp b/src/track.cpp index 4d6c1bb..aa12510 100644 --- a/src/track.cpp +++ b/src/track.cpp @@ -4,10 +4,15 @@ #include "project.h" int sigint; +int tracking; void handler(int signum){ - sigint = 1; - std::cout << std::endl; + if (tracking){ + sigint = 1; + std::cout << std::endl; + } else { + exit(0); + } } void track(Project *proj){ @@ -16,8 +21,11 @@ void track(Project *proj){ time_t start; system("clear"); time(&start); + tracking = 1; std::cout << "Started tracking of task " << proj->name << "/" << proj->active_task->name << " at " << ctime(&start) << std::endl; sigint = 0; + + // will be interrupted by signal handler in case of SIGINT (CTRL-C) while (!sigint){ sleep(1); worktime += 1; @@ -28,4 +36,5 @@ void track(Project *proj){ work_s = worktime % 60; printf("Time worked on project: %02d:%02d:%02d\n", work_h,work_m,work_s ); + tracking = 0; } diff --git a/src/track.h b/src/track.h index 48677a3..7957ed5 100644 --- a/src/track.h +++ b/src/track.h @@ -3,6 +3,7 @@ #include "project.h" extern int sigint; +extern int tracking; void handler(int signum); void track (Project *proj); diff --git a/src/tt.cpp b/src/tt.cpp index 2050915..4928ea8 100644 --- a/src/tt.cpp +++ b/src/tt.cpp @@ -3,12 +3,39 @@ #include #include #include +#include +#include #include "task.h" #include "project.h" #include "track.h" +#include "ui.h" int main(){ + // connect SIGINT signal (CTRL-C) to signal handler from track.h to use it to stop tracking of projects signal(SIGINT, handler); + tracking = 0; + + // TEST: set up test list + ProjectList proj_list; + Project proj("Test Project"); + Task task1("Task 1"),task2("Task2"),task3("Task 3"); + proj.add_task(task1); + proj.add_task(task2); + proj.add_task(task3); + proj_list.add_project(proj); + + init_autocomplete(&proj_list); + + // use GNU readline for auto completion and history when parsing command input + while(1) { + rl_attempted_completion_function = tt_name_completion; + char *buffer = readline("tt> "); + if (buffer){ + printf("Entered: %s\n", buffer); + add_history(buffer); + free(buffer); + } + } return 0; } diff --git a/src/ui.cpp b/src/ui.cpp new file mode 100644 index 0000000..0aaf6bf --- /dev/null +++ b/src/ui.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include "ui.h" +#include "project.h" + +// Use GNU readline library for autocompletion and command history + +std::string command_names[num_commands]={ + "np", + "nt", + "sp", + "st", + "at", + "rt", + "rm", + "report", + "ls", + "start" +}; + +std::vector autocomplete_names; +char **tt_name_completion(const char* text, int start, int end){ + rl_attempted_completion_over = 1; + return rl_completion_matches(text, tt_name_generator); +} + +char *tt_name_generator(const char *text, int state){ + static int idx, len; + const char* name; + + if (!state){ + idx = 0; + len = strlen(text); + } + + while ((name = autocomplete_names[idx++].c_str())){ + if (strncmp(name, text, len) == 0){ + return strdup(name); + + } + } + return NULL; +} + +std::string space_to_underscore(std::string str){ + for(size_t i = 0; i < str.length(); i++){ + if(str[i] == ' ') str[i] = '_'; + } + return str; +} + +void init_autocomplete(ProjectList *proj_list){ + // add command names to auto complete list + for (int i=0; inum_projects; i++){ + autocomplete_names.push_back(space_to_underscore(proj_list->projects[i].name)); + for (int j=0; jprojects[i].num_tasks; j++){ + + std::string tmp = space_to_underscore(proj_list->projects[i].name) + "/" + space_to_underscore(proj_list->projects[i].tasks[j].name); + autocomplete_names.push_back(tmp); + } + } +} diff --git a/src/ui.h b/src/ui.h new file mode 100644 index 0000000..34d52a9 --- /dev/null +++ b/src/ui.h @@ -0,0 +1,15 @@ +#ifndef UI_H +#define UI_H + +#include +#include +#include "project.h" + +const int num_commands=10; +extern std::string command_names[num_commands]; +extern std::vector autocomplete_names; +char **tt_name_completion(const char* text, int start, int end); +char *tt_name_generator(const char *text, int state); +void init_autocomplete(ProjectList *proj_list); +std::string space_to_underscore(std::string); +#endif