From b6c5fef45eaadce4463ee60e60eb0a0252b61255 Mon Sep 17 00:00:00 2001 From: James Booth Date: Mon, 30 Apr 2012 01:09:42 +0100 Subject: [PATCH] Started work on bash style history --- .gitignore | 1 + Makefile | 10 +++-- prof_history.c | 91 +++++++++++++++++++++++++++++++++++++++++++++ prof_history.h | 11 ++++++ test_prof_history.c | 49 ++++++++++++++++++++++++ testsuite.c | 1 + testsuite.h | 1 + 7 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 prof_history.c create mode 100644 prof_history.h create mode 100644 test_prof_history.c diff --git a/.gitignore b/.gitignore index 14dbc57b..85d548f8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ profanity *.log *.swp testsuite +tags diff --git a/Makefile b/Makefile index 698939ec..be25a2aa 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,15 @@ CC = gcc -WARNS = -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-but-set-variable +WARNS = -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-but-set-variable \ + -Wno-unused-result LIBS = -lxml2 -lexpat -lssl -lresolv -lncurses -L ~/lib -lstrophe `pkg-config --libs glib-2.0` TESTLIB = -L ~/lib -l headunit CPPLIB = -lstdc++ CFLAGS = -I ~/include -O3 $(WARNS) $(LIBS) `pkg-config --cflags glib-2.0` OBJS = log.o windows.o title_bar.o status_bar.o input_win.o jabber.o \ - profanity.o util.o command.o history.o contact_list.o main.o + profanity.o util.o command.o history.o contact_list.o prof_history.o \ + main.o TESTOBJS = test_history.o history.o test_contact_list.o contact_list.o \ - test_util.o util.o + test_util.o test_prof_history.o prof_history.o util.o profanity: $(OBJS) $(CC) -o profanity $(OBJS) $(LIBS) @@ -23,11 +25,13 @@ util.o: util.h command.o: command.h util.h history.h contact_list.h history.o: history.h contact_list.o: contact_list.h +prof_history.o: prof_history.h main.o: profanity.h test_history.o: history.h test_contact_list.o: contact_list.h test_util.o: util.h +test_prof_history.o: prof_history.h testsuite: testsuite.h $(TESTOBJS) $(CC) $(CFLAGS) $(CPPLIB) testsuite.c $(TESTOBJS) -o testsuite $(TESTLIB) diff --git a/prof_history.c b/prof_history.c new file mode 100644 index 00000000..3aca0150 --- /dev/null +++ b/prof_history.c @@ -0,0 +1,91 @@ +#include +#include +#include + +#include + +#include "prof_history.h" + +struct p_history_t { + GList *items; // the history + GList *session; // a copy of the history for edits + GList *session_current; // pointer to the current item in the session + guint max_size; +}; + +PHistory p_history_new(unsigned int size) +{ + PHistory new_history = malloc(sizeof(struct p_history_t)); + new_history->items = NULL; + new_history->session = NULL; + new_history->max_size = size; + + return new_history; +} + +void p_history_append(PHistory history, char *item) +{ + char *copied = strdup(item); + // if already at max size + if (g_list_length(history->items) == history->max_size) { + + // remove first element + GList *first = g_list_first(history->items); + const char *first_item = (char *) first->data; + history->items = g_list_remove(history->items, first_item); + } + + // append the new item onto the history + history->items = g_list_append(history->items, copied); + + // delete the current session + if (history->session != NULL) { + g_list_free(history->session); + history->session = NULL; + } +} + +char * p_history_previous(PHistory history) +{ + if (history->items == NULL) { + return NULL; + } + + if (history->session == NULL) { + history->session = g_list_copy(history->items); + history->session_current = g_list_last(history->session); + } else { + history->session_current = g_list_previous(history->session_current); + } + + // set to first if rolled over beginning + if (history->session_current == NULL) { + history->session_current = g_list_first(history->session); + } + + char *item = (char *) history->session_current->data; + char *result = malloc((strlen(item) + 1) * sizeof(char)); + strcpy(result, item); + + return result; +} + +char * p_history_next(PHistory history) +{ + if (history->session == NULL) { + return NULL; + } else { + history->session_current = g_list_next(history->session_current); + } + + // set to last if rolled over end + if (history->session_current == NULL) { + history->session_current = g_list_last(history->session); + } + + char *item = (char *) history->session_current->data; + char *result = malloc((strlen(item) + 1) * sizeof(char)); + strcpy(result, item); + + return result; +} diff --git a/prof_history.h b/prof_history.h new file mode 100644 index 00000000..5c2acaaf --- /dev/null +++ b/prof_history.h @@ -0,0 +1,11 @@ +#ifndef PROF_HISTORY_H +#define PROF_HISTORY_H + +typedef struct p_history_t *PHistory; + +PHistory p_history_new(unsigned int size); +char * p_history_previous(PHistory history); +char * p_history_next(PHistory history); +void p_history_append(PHistory history, char *item); + +#endif diff --git a/test_prof_history.c b/test_prof_history.c new file mode 100644 index 00000000..5a9ae217 --- /dev/null +++ b/test_prof_history.c @@ -0,0 +1,49 @@ +#include +#include +#include "prof_history.h" + +void previous_on_empty_returns_null(void) +{ + PHistory history = p_history_new(10); + char *item = p_history_previous(history); + + assert_is_null(item); +} + +void next_on_empty_returns_null(void) +{ + PHistory history = p_history_new(10); + char *item = p_history_next(history); + + assert_is_null(item); +} + +void previous_once_returns_last(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + + char *item = p_history_previous(history); + + assert_string_equals("Hello", item); +} + +void previous_twice_when_one_returns_first(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + + p_history_previous(history); + char *item = p_history_previous(history); + + assert_string_equals("Hello", item); +} + +void register_prof_history_tests(void) +{ + TEST_MODULE("prof_history tests"); + TEST(previous_on_empty_returns_null); + TEST(next_on_empty_returns_null); + TEST(previous_once_returns_last); + TEST(previous_twice_when_one_returns_first); +} diff --git a/testsuite.c b/testsuite.c index 88c9cdc1..7a6ab3b2 100644 --- a/testsuite.c +++ b/testsuite.c @@ -4,6 +4,7 @@ int main(void) { register_history_tests(); + register_prof_history_tests(); register_contact_list_tests(); register_util_tests(); run_suite(); diff --git a/testsuite.h b/testsuite.h index 2aa34ca5..90a2d34b 100644 --- a/testsuite.h +++ b/testsuite.h @@ -2,6 +2,7 @@ #define TESTSUITE_H void register_history_tests(void); +void register_prof_history_tests(void); void register_contact_list_tests(void); void register_util_tests(void);