From 1730372e00a7469a05c7535c68dbfab83f8af0b4 Mon Sep 17 00:00:00 2001 From: James Booth Date: Tue, 1 May 2012 00:24:31 +0100 Subject: [PATCH] Bash style history --- Makefile | 7 +-- command.c | 5 ++ command.h | 2 +- history.c | 64 +++++++++------------- history.h | 6 +- input_win.c | 4 +- prof_history.c | 25 +++------ profanity.c | 3 +- test_history.c | 130 -------------------------------------------- test_prof_history.c | 107 ++++++++++++++++++++++++++++++++++-- testsuite.c | 1 - testsuite.h | 1 - 12 files changed, 152 insertions(+), 203 deletions(-) delete mode 100644 test_history.c diff --git a/Makefile b/Makefile index be25a2aa..61210e29 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ 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 prof_history.o \ main.o -TESTOBJS = test_history.o history.o test_contact_list.o contact_list.o \ +TESTOBJS = test_contact_list.o contact_list.o \ test_util.o test_prof_history.o prof_history.o util.o profanity: $(OBJS) @@ -20,15 +20,14 @@ title_bar.o: windows.h status_bar.o: windows.h util.h input_win.o: windows.h jabber.o: jabber.h log.h windows.h contact_list.h -profanity.o: log.h windows.h jabber.h command.h history.h +profanity.o: log.h windows.h jabber.h command.h util.o: util.h command.o: command.h util.h history.h contact_list.h -history.o: history.h +history.o: history.h prof_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 diff --git a/command.c b/command.c index 17c2dcb0..1de58310 100644 --- a/command.c +++ b/command.c @@ -72,6 +72,11 @@ gboolean process_input(char *inp) return result; } +void command_init(void) +{ + history_init(); +} + static gboolean _handle_command(const char * const command, const char * const inp) { gboolean result = FALSE; diff --git a/command.h b/command.h index d0d57022..9da8838c 100644 --- a/command.h +++ b/command.h @@ -23,7 +23,7 @@ #ifndef COMMAND_H #define COMMAND_H -void cmd_init(void); +void command_init(void); gboolean process_input(char *inp); #endif diff --git a/history.c b/history.c index 00b06582..a7b570f8 100644 --- a/history.c +++ b/history.c @@ -23,53 +23,43 @@ #include #include +#include "prof_history.h" + #define MAX_HISTORY 100 -static char *_history[MAX_HISTORY]; -static int _size; -static int _pos; +static PHistory history; void history_init(void) { + history = p_history_new(MAX_HISTORY); +} + +void history_append(char *inp) +{ + p_history_append(history, inp); +} + +char * history_previous(char *inp, int *size) +{ + char inp_str[*size + 1]; int i; - for (i = 0; i < _size; i++) - free(_history[i]); - - _size = 0; - _pos = -1; -} - -// FIXME: Roll history when full -void history_append(const char * const inp) -{ - if (_size < MAX_HISTORY) { - _history[_size] = (char*) malloc((strlen(inp) + 1) * sizeof(char)); - strcpy(_history[_size], inp); - _pos = _size; - _size++; + for (i = 0; i < *size; i++) { + inp_str[i] = inp[i]; } + inp_str[*size] = '\0'; + + return p_history_previous(history, inp_str); } -char *history_previous(void) +char *history_next(char *inp, int *size) { - if (_size == 0 || _pos == -1) - return NULL; + char inp_str[*size + 1]; + int i; + for (i = 0; i < *size; i++) { + inp_str[i] = inp[i]; + } + inp_str[*size] = '\0'; - return _history[_pos--]; -} - -char *history_next(void) -{ - if (_size == 0) - return NULL; - if (_pos == (_size - 1)) - return NULL; - if (_pos + 2 >= _size) - return NULL; - - int pos = _pos + 2; - _pos++; - - return _history[pos]; + return p_history_next(history, inp_str); } diff --git a/history.h b/history.h index 7afca5e1..a65ac397 100644 --- a/history.h +++ b/history.h @@ -25,8 +25,8 @@ #define HISTORY_H void history_init(void); -void history_append(const char * const inp); -char *history_previous(void); -char *history_next(void); +void history_append(char *inp); +char *history_previous(char *inp, int *size); +char *history_next(char *inp, int *size); #endif diff --git a/input_win.c b/input_win.c index f0cd364f..5ed17d05 100644 --- a/input_win.c +++ b/input_win.c @@ -210,13 +210,13 @@ static int _handle_edit(const int ch, char *input, int *size) return 1; case KEY_UP: - prev = history_previous(); + prev = history_previous(input, size); if (prev) _replace_input(input, prev, size); return 1; case KEY_DOWN: - next = history_next(); + next = history_next(input, size); if (next) _replace_input(input, next, size); return 1; diff --git a/prof_history.c b/prof_history.c index e896ac15..cf82fafd 100644 --- a/prof_history.c +++ b/prof_history.c @@ -62,26 +62,19 @@ void p_history_append(PHistory history, char *item) } else { // if adding a new item, copy the session over the history - if ((history->sess_new != NULL) && - (history->sess_curr == history->sess_new)) { + if (history->sess_curr == history->sess_new) { + history->sess_curr->data = copied; _replace_history_with_session(history); // otherwise, adding edited history item } else { - - // discard the new item if there was one if (history->sess_new != NULL) { - history->session = g_list_reverse(history->session); - GList *first = g_list_first(history->session); - char *first_item = first->data; - history->session = g_list_remove(history->session, first_item); - history->session = g_list_reverse(history->session); + // copy the current string to the last element in session + history->sess_new->data = copied; + } else { + g_list_append(history->session, copied); } - - // copy sess_curr to the end of the session - char *new_data = strdup(history->sess_curr->data); - history->session = g_list_append(history->session, new_data); - + // replace the edited version with the data from the history history->sess_curr->data = strdup(history->items_curr->data); @@ -114,7 +107,7 @@ char * p_history_previous(PHistory history, char *item) { // no history if (history->items == NULL) { - return item; + return NULL; } char *copied = ""; @@ -160,7 +153,7 @@ char * p_history_next(PHistory history, char *item) // no history, or no session, return item if ((history->items == NULL) || (history->session == NULL)) { - return item; + return NULL; } char *copied = ""; diff --git a/profanity.c b/profanity.c index de26f8b8..f87fca6a 100644 --- a/profanity.c +++ b/profanity.c @@ -29,7 +29,6 @@ #include "windows.h" #include "jabber.h" #include "command.h" -#include "history.h" static void _profanity_shutdown(void); @@ -67,7 +66,7 @@ void profanity_init(const int disable_tls) log_init(); gui_init(); jabber_init(disable_tls); - history_init(); + command_init(); atexit(_profanity_shutdown); } diff --git a/test_history.c b/test_history.c deleted file mode 100644 index f455d7d1..00000000 --- a/test_history.c +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include -#include "history.h" - -static void beforetest(void) -{ - history_init(); -} - -static void previous_returns_null_after_init(void) -{ - char *prev = history_previous(); - assert_is_null(prev); -} - -static void next_returns_null_after_init(void) -{ - char *next = history_next(); - assert_is_null(next); -} - -static void append_after_init_doesnt_fail(void) -{ - history_append("try append"); - assert_true(1); -} - -static void append_then_previous_returns_appended(void) -{ - history_append("try append"); - char *prev = history_previous(); - assert_string_equals("try append", prev); -} - -static void append_then_next_returns_null(void) -{ - history_append("try append"); - char *next = history_next(); - assert_is_null(next); -} - -static void hits_null_at_top(void) -{ - history_append("cmd1"); - history_append("cmd2"); - history_previous(); // cmd2 - history_previous(); // cmd1 - char *prev = history_previous(); - assert_is_null(prev); -} - -static void navigate_to_correct_item(void) -{ - history_append("cmd1"); - history_append("cmd2"); - history_append("cmd3"); - history_append("cmd4"); - history_append("cmd5"); - history_append("cmd6"); - - history_previous(); // cmd6 - history_previous(); // cmd5 - history_previous(); // cmd4 - history_previous(); // cmd3 - history_next(); // cmd4 - history_previous(); // cmd3 - history_previous(); // cmd2 - char *str = history_next(); // cmd3 - - assert_string_equals("cmd3", str); -} - -static void append_previous_item(void) -{ - history_append("cmd1"); - history_append("cmd2"); - history_append("cmd3"); - history_append("cmd4"); - history_append("cmd5"); - history_append("cmd6"); - - history_previous(); // cmd6 - history_previous(); // cmd5 - history_previous(); // cmd4 - history_previous(); // cmd3 - history_next(); // cmd4 - history_previous(); // cmd3 - history_previous(); // cmd2 - char *str = history_next(); // cmd3 - - history_append(str); - - char *cmd3_1 = history_previous(); - assert_string_equals("cmd3", cmd3_1); - - char *cmd6 = history_previous(); - assert_string_equals("cmd6", cmd6); - - char *cmd5 = history_previous(); - assert_string_equals("cmd5", cmd5); - - char *cmd4 = history_previous(); - assert_string_equals("cmd4", cmd4); - - char *cmd3 = history_previous(); - assert_string_equals("cmd3", cmd3); - - char *cmd2 = history_previous(); - assert_string_equals("cmd2", cmd2); - - char *cmd1 = history_previous(); - assert_string_equals("cmd1", cmd1); - - char *end = history_previous(); - assert_is_null(end); -} - -void register_history_tests(void) -{ - TEST_MODULE("history tests"); - BEFORETEST(beforetest); - TEST(previous_returns_null_after_init); - TEST(next_returns_null_after_init); - TEST(append_after_init_doesnt_fail); - TEST(append_then_previous_returns_appended); - TEST(append_then_next_returns_null); - TEST(hits_null_at_top); - TEST(navigate_to_correct_item); - TEST(append_previous_item); -} diff --git a/test_prof_history.c b/test_prof_history.c index 6b42a160..69028609 100644 --- a/test_prof_history.c +++ b/test_prof_history.c @@ -2,20 +2,20 @@ #include #include "prof_history.h" -void previous_on_empty_returns_current(void) +void previous_on_empty_returns_null(void) { PHistory history = p_history_new(10); char *item = p_history_previous(history, "inp"); - assert_string_equals("inp", item); + assert_is_null(item); } -void next_on_empty_returns_current(void) +void next_on_empty_returns_null(void) { PHistory history = p_history_new(10); char *item = p_history_next(history, "inp"); - assert_string_equals("inp", item); + assert_is_null(item); } void previous_once_returns_last(void) @@ -105,11 +105,103 @@ void prev_with_val_then_next_twice_returns_val(void) assert_string_equals("Oioi", item3); } +void navigate_then_append_new(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + p_history_append(history, "again"); + p_history_append(history, "testing"); + p_history_append(history, "history"); + p_history_append(history, "append"); + + char *item1 = p_history_previous(history, "new text"); + assert_string_equals("append", item1); + + char *item2 = p_history_previous(history, item1); + assert_string_equals("history", item2); + + char *item3 = p_history_previous(history, item2); + assert_string_equals("testing", item3); + + char *item4 = p_history_next(history, item3); + assert_string_equals("history", item4); + + char *item5 = p_history_next(history, item4); + assert_string_equals("append", item5); + + char *item6 = p_history_next(history, item5); + assert_string_equals("new text", item6); +} + +void edit_item_mid_history(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + p_history_append(history, "again"); + p_history_append(history, "testing"); + p_history_append(history, "history"); + p_history_append(history, "append"); + + char *item1 = p_history_previous(history, "new item"); + assert_string_equals("append", item1); + + char *item2 = p_history_previous(history, item1); + assert_string_equals("history", item2); + + char *item3 = p_history_previous(history, item2); + assert_string_equals("testing", item3); + + char *item4 = p_history_previous(history, "EDITED"); + assert_string_equals("again", item4); + + char *item5 = p_history_previous(history, item4); + assert_string_equals("Hello", item5); + + char *item6 = p_history_next(history, item5); + assert_string_equals("again", item6); + + char *item7 = p_history_next(history, item6); + assert_string_equals("EDITED", item7); + + char *item8 = p_history_next(history, item7); + assert_string_equals("history", item8); + + char *item9 = p_history_next(history, item8); + assert_string_equals("append", item9); + + char *item10 = p_history_next(history, item9); + assert_string_equals("new item", item10); +} + +void edit_previous_and_append(void) +{ + PHistory history = p_history_new(10); + p_history_append(history, "Hello"); + p_history_append(history, "again"); + p_history_append(history, "testing"); + p_history_append(history, "history"); + p_history_append(history, "append"); + + char *item1 = p_history_previous(history, "new item"); + assert_string_equals("append", item1); + + char *item2 = p_history_previous(history, item1); + assert_string_equals("history", item2); + + char *item3 = p_history_previous(history, item2); + assert_string_equals("testing", item3); + + p_history_append(history, "EDITED"); + + char *item4 = p_history_previous(history, NULL); + assert_string_equals("EDITED", item4); +} + void register_prof_history_tests(void) { TEST_MODULE("prof_history tests"); - TEST(previous_on_empty_returns_current); - TEST(next_on_empty_returns_current); + TEST(previous_on_empty_returns_null); + TEST(next_on_empty_returns_null); TEST(previous_once_returns_last); TEST(previous_twice_when_one_returns_first); TEST(previous_always_stops_at_first); @@ -117,4 +209,7 @@ void register_prof_history_tests(void) TEST(prev_then_next_returns_empty); TEST(prev_with_val_then_next_returns_val); TEST(prev_with_val_then_next_twice_returns_val); + TEST(navigate_then_append_new); + TEST(edit_item_mid_history); + TEST(edit_previous_and_append); } diff --git a/testsuite.c b/testsuite.c index 7a6ab3b2..e6eb6d0b 100644 --- a/testsuite.c +++ b/testsuite.c @@ -3,7 +3,6 @@ int main(void) { - register_history_tests(); register_prof_history_tests(); register_contact_list_tests(); register_util_tests(); diff --git a/testsuite.h b/testsuite.h index 90a2d34b..410b3e47 100644 --- a/testsuite.h +++ b/testsuite.h @@ -1,7 +1,6 @@ #ifndef TESTSUITE_H #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);