Basic UI implemented usinf GNU readline

This commit is contained in:
Patrick Lipka 2021-12-10 11:09:03 +01:00
parent d19d96b6ee
commit 363372f34e
6 changed files with 126 additions and 3 deletions

View File

@ -1,6 +1,7 @@
CXX ?= g++ CXX ?= g++
CXXFLAGS := -g -Wall -pedantic CXXFLAGS := -g -Wall -pedantic
OBJFLAGS := $(CXXFLAGS) -c OBJFLAGS := $(CXXFLAGS) -c
LDFLAGS := -lreadline
BIN_PATH := bin BIN_PATH := bin
SRC_PATH := src SRC_PATH := src
@ -11,7 +12,7 @@ OBJ := $(addprefix $(SRC_PATH)/, $(addsuffix .o, $(notdir $(basename $(SRC)))))
default: makedir all default: makedir all
$(BIN_PATH)/tt: $(OBJ) $(BIN_PATH)/tt: $(OBJ)
$(CXX) $(CXXFLAGS) -o $@ $(OBJ) $(CXX) $(CXXFLAGS) -o $@ $(OBJ) $(LDFLAGS)
$(SRC_PATH)/%.o: $(SRC_PATH)/%.cpp $(SRC_PATH)/%.o: $(SRC_PATH)/%.cpp
$(CXX) $(OBJFLAGS) -o $@ $< $(CXX) $(OBJFLAGS) -o $@ $<

View File

@ -4,10 +4,15 @@
#include "project.h" #include "project.h"
int sigint; int sigint;
int tracking;
void handler(int signum){ void handler(int signum){
if (tracking){
sigint = 1; sigint = 1;
std::cout << std::endl; std::cout << std::endl;
} else {
exit(0);
}
} }
void track(Project *proj){ void track(Project *proj){
@ -16,8 +21,11 @@ void track(Project *proj){
time_t start; time_t start;
system("clear"); system("clear");
time(&start); time(&start);
tracking = 1;
std::cout << "Started tracking of task " << proj->name << "/" << proj->active_task->name << " at " << ctime(&start) << std::endl; std::cout << "Started tracking of task " << proj->name << "/" << proj->active_task->name << " at " << ctime(&start) << std::endl;
sigint = 0; sigint = 0;
// will be interrupted by signal handler in case of SIGINT (CTRL-C)
while (!sigint){ while (!sigint){
sleep(1); sleep(1);
worktime += 1; worktime += 1;
@ -28,4 +36,5 @@ void track(Project *proj){
work_s = worktime % 60; work_s = worktime % 60;
printf("Time worked on project: %02d:%02d:%02d\n", work_h,work_m,work_s ); printf("Time worked on project: %02d:%02d:%02d\n", work_h,work_m,work_s );
tracking = 0;
} }

View File

@ -3,6 +3,7 @@
#include "project.h" #include "project.h"
extern int sigint; extern int sigint;
extern int tracking;
void handler(int signum); void handler(int signum);
void track (Project *proj); void track (Project *proj);

View File

@ -3,12 +3,39 @@
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "task.h" #include "task.h"
#include "project.h" #include "project.h"
#include "track.h" #include "track.h"
#include "ui.h"
int main(){ int main(){
// connect SIGINT signal (CTRL-C) to signal handler from track.h to use it to stop tracking of projects
signal(SIGINT, handler); 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; return 0;
} }

70
src/ui.cpp Normal file
View File

@ -0,0 +1,70 @@
#include <iostream>
#include <vector>
#include <string>
#include <readline/readline.h>
#include <readline/history.h>
#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<std::string> 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; i<num_commands; i++){
autocomplete_names.push_back(command_names[i]);
}
// add project/task names to auto complete list
for (int i=0; i<proj_list->num_projects; i++){
autocomplete_names.push_back(space_to_underscore(proj_list->projects[i].name));
for (int j=0; j<proj_list->projects[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);
}
}
}

15
src/ui.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef UI_H
#define UI_H
#include <vector>
#include <string>
#include "project.h"
const int num_commands=10;
extern std::string command_names[num_commands];
extern std::vector<std::string> 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