about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJames Booth <boothj5@gmail.com>2012-04-30 01:09:42 +0100
committerJames Booth <boothj5@gmail.com>2012-04-30 01:09:42 +0100
commitb6c5fef45eaadce4463ee60e60eb0a0252b61255 (patch)
tree2ddb6ce1f874413648a7dcd74fb03f7c41ec95da
parentc511d7c99f792823fd2727d3a5a1f1fd722b8a33 (diff)
downloadprofani-tty-b6c5fef45eaadce4463ee60e60eb0a0252b61255.tar.gz
Started work on bash style history
-rw-r--r--.gitignore1
-rw-r--r--Makefile10
-rw-r--r--prof_history.c91
-rw-r--r--prof_history.h11
-rw-r--r--test_prof_history.c49
-rw-r--r--testsuite.c1
-rw-r--r--testsuite.h1
7 files changed, 161 insertions, 3 deletions
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#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 <stdio.h>
+#include <head-unit.h>
+#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);