mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Bash style history
This commit is contained in:
parent
4531aebd29
commit
1730372e00
7
Makefile
7
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 \
|
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 \
|
profanity.o util.o command.o history.o contact_list.o prof_history.o \
|
||||||
main.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
|
test_util.o test_prof_history.o prof_history.o util.o
|
||||||
|
|
||||||
profanity: $(OBJS)
|
profanity: $(OBJS)
|
||||||
@ -20,15 +20,14 @@ title_bar.o: windows.h
|
|||||||
status_bar.o: windows.h util.h
|
status_bar.o: windows.h util.h
|
||||||
input_win.o: windows.h
|
input_win.o: windows.h
|
||||||
jabber.o: jabber.h log.h windows.h contact_list.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
|
util.o: util.h
|
||||||
command.o: command.h util.h history.h contact_list.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
|
contact_list.o: contact_list.h
|
||||||
prof_history.o: prof_history.h
|
prof_history.o: prof_history.h
|
||||||
main.o: profanity.h
|
main.o: profanity.h
|
||||||
|
|
||||||
test_history.o: history.h
|
|
||||||
test_contact_list.o: contact_list.h
|
test_contact_list.o: contact_list.h
|
||||||
test_util.o: util.h
|
test_util.o: util.h
|
||||||
test_prof_history.o: prof_history.h
|
test_prof_history.o: prof_history.h
|
||||||
|
@ -72,6 +72,11 @@ gboolean process_input(char *inp)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command_init(void)
|
||||||
|
{
|
||||||
|
history_init();
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean _handle_command(const char * const command, const char * const inp)
|
static gboolean _handle_command(const char * const command, const char * const inp)
|
||||||
{
|
{
|
||||||
gboolean result = FALSE;
|
gboolean result = FALSE;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#ifndef COMMAND_H
|
#ifndef COMMAND_H
|
||||||
#define COMMAND_H
|
#define COMMAND_H
|
||||||
|
|
||||||
void cmd_init(void);
|
void command_init(void);
|
||||||
gboolean process_input(char *inp);
|
gboolean process_input(char *inp);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
64
history.c
64
history.c
@ -23,53 +23,43 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "prof_history.h"
|
||||||
|
|
||||||
#define MAX_HISTORY 100
|
#define MAX_HISTORY 100
|
||||||
|
|
||||||
static char *_history[MAX_HISTORY];
|
static PHistory history;
|
||||||
static int _size;
|
|
||||||
static int _pos;
|
|
||||||
|
|
||||||
void history_init(void)
|
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;
|
int i;
|
||||||
for (i = 0; i < _size; i++)
|
for (i = 0; i < *size; i++) {
|
||||||
free(_history[i]);
|
inp_str[i] = inp[i];
|
||||||
|
}
|
||||||
|
inp_str[*size] = '\0';
|
||||||
|
|
||||||
_size = 0;
|
return p_history_previous(history, inp_str);
|
||||||
_pos = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Roll history when full
|
char *history_next(char *inp, int *size)
|
||||||
void history_append(const char * const inp)
|
|
||||||
{
|
{
|
||||||
if (_size < MAX_HISTORY) {
|
char inp_str[*size + 1];
|
||||||
_history[_size] = (char*) malloc((strlen(inp) + 1) * sizeof(char));
|
int i;
|
||||||
strcpy(_history[_size], inp);
|
for (i = 0; i < *size; i++) {
|
||||||
_pos = _size;
|
inp_str[i] = inp[i];
|
||||||
_size++;
|
|
||||||
}
|
}
|
||||||
}
|
inp_str[*size] = '\0';
|
||||||
|
|
||||||
char *history_previous(void)
|
return p_history_next(history, inp_str);
|
||||||
{
|
|
||||||
if (_size == 0 || _pos == -1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#define HISTORY_H
|
#define HISTORY_H
|
||||||
|
|
||||||
void history_init(void);
|
void history_init(void);
|
||||||
void history_append(const char * const inp);
|
void history_append(char *inp);
|
||||||
char *history_previous(void);
|
char *history_previous(char *inp, int *size);
|
||||||
char *history_next(void);
|
char *history_next(char *inp, int *size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -210,13 +210,13 @@ static int _handle_edit(const int ch, char *input, int *size)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
prev = history_previous();
|
prev = history_previous(input, size);
|
||||||
if (prev)
|
if (prev)
|
||||||
_replace_input(input, prev, size);
|
_replace_input(input, prev, size);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
next = history_next();
|
next = history_next(input, size);
|
||||||
if (next)
|
if (next)
|
||||||
_replace_input(input, next, size);
|
_replace_input(input, next, size);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -62,26 +62,19 @@ void p_history_append(PHistory history, char *item)
|
|||||||
} else {
|
} else {
|
||||||
|
|
||||||
// if adding a new item, copy the session over the history
|
// if adding a new item, copy the session over the history
|
||||||
if ((history->sess_new != NULL) &&
|
if (history->sess_curr == history->sess_new) {
|
||||||
(history->sess_curr == history->sess_new)) {
|
history->sess_curr->data = copied;
|
||||||
_replace_history_with_session(history);
|
_replace_history_with_session(history);
|
||||||
|
|
||||||
// otherwise, adding edited history item
|
// otherwise, adding edited history item
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// discard the new item if there was one
|
|
||||||
if (history->sess_new != NULL) {
|
if (history->sess_new != NULL) {
|
||||||
history->session = g_list_reverse(history->session);
|
// copy the current string to the last element in session
|
||||||
GList *first = g_list_first(history->session);
|
history->sess_new->data = copied;
|
||||||
char *first_item = first->data;
|
} else {
|
||||||
history->session = g_list_remove(history->session, first_item);
|
g_list_append(history->session, copied);
|
||||||
history->session = g_list_reverse(history->session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// replace the edited version with the data from the history
|
||||||
history->sess_curr->data = strdup(history->items_curr->data);
|
history->sess_curr->data = strdup(history->items_curr->data);
|
||||||
|
|
||||||
@ -114,7 +107,7 @@ char * p_history_previous(PHistory history, char *item)
|
|||||||
{
|
{
|
||||||
// no history
|
// no history
|
||||||
if (history->items == NULL) {
|
if (history->items == NULL) {
|
||||||
return item;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *copied = "";
|
char *copied = "";
|
||||||
@ -160,7 +153,7 @@ char * p_history_next(PHistory history, char *item)
|
|||||||
|
|
||||||
// no history, or no session, return item
|
// no history, or no session, return item
|
||||||
if ((history->items == NULL) || (history->session == NULL)) {
|
if ((history->items == NULL) || (history->session == NULL)) {
|
||||||
return item;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *copied = "";
|
char *copied = "";
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#include "windows.h"
|
#include "windows.h"
|
||||||
#include "jabber.h"
|
#include "jabber.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "history.h"
|
|
||||||
|
|
||||||
static void _profanity_shutdown(void);
|
static void _profanity_shutdown(void);
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ void profanity_init(const int disable_tls)
|
|||||||
log_init();
|
log_init();
|
||||||
gui_init();
|
gui_init();
|
||||||
jabber_init(disable_tls);
|
jabber_init(disable_tls);
|
||||||
history_init();
|
command_init();
|
||||||
atexit(_profanity_shutdown);
|
atexit(_profanity_shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
test_history.c
130
test_history.c
@ -1,130 +0,0 @@
|
|||||||
#include <stdlib.h>
|
|
||||||
#include <head-unit.h>
|
|
||||||
#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);
|
|
||||||
}
|
|
@ -2,20 +2,20 @@
|
|||||||
#include <head-unit.h>
|
#include <head-unit.h>
|
||||||
#include "prof_history.h"
|
#include "prof_history.h"
|
||||||
|
|
||||||
void previous_on_empty_returns_current(void)
|
void previous_on_empty_returns_null(void)
|
||||||
{
|
{
|
||||||
PHistory history = p_history_new(10);
|
PHistory history = p_history_new(10);
|
||||||
char *item = p_history_previous(history, "inp");
|
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);
|
PHistory history = p_history_new(10);
|
||||||
char *item = p_history_next(history, "inp");
|
char *item = p_history_next(history, "inp");
|
||||||
|
|
||||||
assert_string_equals("inp", item);
|
assert_is_null(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void previous_once_returns_last(void)
|
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);
|
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)
|
void register_prof_history_tests(void)
|
||||||
{
|
{
|
||||||
TEST_MODULE("prof_history tests");
|
TEST_MODULE("prof_history tests");
|
||||||
TEST(previous_on_empty_returns_current);
|
TEST(previous_on_empty_returns_null);
|
||||||
TEST(next_on_empty_returns_current);
|
TEST(next_on_empty_returns_null);
|
||||||
TEST(previous_once_returns_last);
|
TEST(previous_once_returns_last);
|
||||||
TEST(previous_twice_when_one_returns_first);
|
TEST(previous_twice_when_one_returns_first);
|
||||||
TEST(previous_always_stops_at_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_then_next_returns_empty);
|
||||||
TEST(prev_with_val_then_next_returns_val);
|
TEST(prev_with_val_then_next_returns_val);
|
||||||
TEST(prev_with_val_then_next_twice_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);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
register_history_tests();
|
|
||||||
register_prof_history_tests();
|
register_prof_history_tests();
|
||||||
register_contact_list_tests();
|
register_contact_list_tests();
|
||||||
register_util_tests();
|
register_util_tests();
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef TESTSUITE_H
|
#ifndef TESTSUITE_H
|
||||||
#define TESTSUITE_H
|
#define TESTSUITE_H
|
||||||
|
|
||||||
void register_history_tests(void);
|
|
||||||
void register_prof_history_tests(void);
|
void register_prof_history_tests(void);
|
||||||
void register_contact_list_tests(void);
|
void register_contact_list_tests(void);
|
||||||
void register_util_tests(void);
|
void register_util_tests(void);
|
||||||
|
Loading…
Reference in New Issue
Block a user