edit: Use struct dl_list for history buffer
This commit is contained in:
parent
31e1206baa
commit
ec9aac9468
2 changed files with 80 additions and 69 deletions
140
src/utils/edit.c
140
src/utils/edit.c
|
@ -17,16 +17,21 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "eloop.h"
|
#include "eloop.h"
|
||||||
|
#include "list.h"
|
||||||
#include "edit.h"
|
#include "edit.h"
|
||||||
|
|
||||||
#define CMD_BUF_LEN 256
|
#define CMD_BUF_LEN 256
|
||||||
static char cmdbuf[CMD_BUF_LEN];
|
static char cmdbuf[CMD_BUF_LEN];
|
||||||
static int cmdbuf_pos = 0;
|
static int cmdbuf_pos = 0;
|
||||||
static int cmdbuf_len = 0;
|
static int cmdbuf_len = 0;
|
||||||
#define CMD_HISTORY_LEN 20
|
|
||||||
static char history_buf[CMD_HISTORY_LEN][CMD_BUF_LEN];
|
struct edit_history {
|
||||||
static int history_pos = 0;
|
struct dl_list list;
|
||||||
static int history_current = 0;
|
char str[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dl_list history_list;
|
||||||
|
static struct edit_history *history_curr;
|
||||||
|
|
||||||
static void *edit_cb_ctx;
|
static void *edit_cb_ctx;
|
||||||
static void (*edit_cmd_cb)(void *ctx, char *cmd);
|
static void (*edit_cmd_cb)(void *ctx, char *cmd);
|
||||||
|
@ -171,87 +176,84 @@ static void clear_right(void)
|
||||||
|
|
||||||
static void history_add(const char *str)
|
static void history_add(const char *str)
|
||||||
{
|
{
|
||||||
int prev;
|
struct edit_history *h, *match = NULL;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
if (str[0] == '\0')
|
if (str[0] == '\0')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (history_pos == 0)
|
dl_list_for_each(h, &history_list, struct edit_history, list) {
|
||||||
prev = CMD_HISTORY_LEN - 1;
|
if (os_strcmp(str, h->str) == 0) {
|
||||||
else
|
match = h;
|
||||||
prev = history_pos - 1;
|
break;
|
||||||
if (os_strcmp(history_buf[prev], str) == 0)
|
}
|
||||||
return;
|
}
|
||||||
|
|
||||||
os_strlcpy(history_buf[history_pos], str, CMD_BUF_LEN);
|
if (match) {
|
||||||
history_pos++;
|
dl_list_del(&h->list);
|
||||||
if (history_pos == CMD_HISTORY_LEN)
|
dl_list_add(&history_list, &h->list);
|
||||||
history_pos = 0;
|
history_curr = h;
|
||||||
history_current = history_pos;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = os_strlen(str);
|
||||||
|
h = os_zalloc(sizeof(*h) + len);
|
||||||
|
if (h == NULL)
|
||||||
|
return;
|
||||||
|
dl_list_add(&history_list, &h->list);
|
||||||
|
os_strlcpy(h->str, str, len + 1);
|
||||||
|
history_curr = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void history_use(void)
|
||||||
|
{
|
||||||
|
edit_clear_line();
|
||||||
|
cmdbuf_len = cmdbuf_pos = os_strlen(history_curr->str);
|
||||||
|
os_memcpy(cmdbuf, history_curr->str, cmdbuf_len);
|
||||||
|
edit_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void history_prev(void)
|
static void history_prev(void)
|
||||||
{
|
{
|
||||||
int pos;
|
if (history_curr == NULL ||
|
||||||
|
history_curr ==
|
||||||
if (history_current == (history_pos + 1) % CMD_HISTORY_LEN)
|
dl_list_last(&history_list, struct edit_history, list))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pos = history_current;
|
if (history_curr ==
|
||||||
|
dl_list_first(&history_list, struct edit_history, list)) {
|
||||||
if (history_current == history_pos && cmdbuf_len) {
|
|
||||||
cmdbuf[cmdbuf_len] = '\0';
|
cmdbuf[cmdbuf_len] = '\0';
|
||||||
history_add(cmdbuf);
|
history_add(cmdbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos > 0)
|
history_curr = dl_list_entry(history_curr->list.next,
|
||||||
pos--;
|
struct edit_history, list);
|
||||||
else
|
history_use();
|
||||||
pos = CMD_HISTORY_LEN - 1;
|
|
||||||
if (history_buf[pos][0] == '\0')
|
|
||||||
return;
|
|
||||||
history_current = pos;
|
|
||||||
|
|
||||||
edit_clear_line();
|
|
||||||
cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
|
|
||||||
os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
|
|
||||||
edit_redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void history_next(void)
|
static void history_next(void)
|
||||||
{
|
{
|
||||||
if (history_current == history_pos)
|
if (history_curr == NULL ||
|
||||||
|
history_curr ==
|
||||||
|
dl_list_first(&history_list, struct edit_history, list))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
history_current++;
|
history_curr = dl_list_entry(history_curr->list.prev,
|
||||||
if (history_current == CMD_HISTORY_LEN)
|
struct edit_history, list);
|
||||||
history_current = 0;
|
history_use();
|
||||||
|
|
||||||
edit_clear_line();
|
|
||||||
cmdbuf_len = cmdbuf_pos = os_strlen(history_buf[history_current]);
|
|
||||||
os_memcpy(cmdbuf, history_buf[history_current], cmdbuf_len);
|
|
||||||
edit_redraw();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void history_debug_dump(void)
|
static void history_debug_dump(void)
|
||||||
{
|
{
|
||||||
int p;
|
struct edit_history *h;
|
||||||
edit_clear_line();
|
edit_clear_line();
|
||||||
printf("\r");
|
printf("\r");
|
||||||
p = (history_pos + 1) % CMD_HISTORY_LEN;
|
dl_list_for_each_reverse(h, &history_list, struct edit_history, list)
|
||||||
for (;;) {
|
printf("%s%s\n", h == history_curr ? "[C]" : "", h->str);
|
||||||
printf("[%d%s%s] %s\n",
|
|
||||||
p, p == history_current ? "C" : "",
|
|
||||||
p == history_pos ? "P" : "", history_buf[p]);
|
|
||||||
if (p == history_pos)
|
|
||||||
break;
|
|
||||||
p++;
|
|
||||||
if (p == CMD_HISTORY_LEN)
|
|
||||||
p = 0;
|
|
||||||
}
|
|
||||||
edit_redraw();
|
edit_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -797,29 +799,23 @@ static int search_skip;
|
||||||
|
|
||||||
static char * search_find(void)
|
static char * search_find(void)
|
||||||
{
|
{
|
||||||
int pos = history_pos;
|
struct edit_history *h;
|
||||||
size_t len = os_strlen(search_buf);
|
size_t len = os_strlen(search_buf);
|
||||||
int skip = search_skip;
|
int skip = search_skip;
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (;;) {
|
dl_list_for_each(h, &history_list, struct edit_history, list) {
|
||||||
if (pos == 0)
|
if (os_strstr(h->str, search_buf)) {
|
||||||
pos = CMD_HISTORY_LEN - 1;
|
|
||||||
else
|
|
||||||
pos--;
|
|
||||||
if (pos == history_pos) {
|
|
||||||
search_skip = 0;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (os_strstr(history_buf[pos], search_buf)) {
|
|
||||||
if (skip == 0)
|
if (skip == 0)
|
||||||
return history_buf[pos];
|
return h->str;
|
||||||
skip--;
|
skip--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search_skip = 0;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1051,7 +1047,8 @@ int edit_init(void (*cmd_cb)(void *ctx, char *cmd),
|
||||||
void (*eof_cb)(void *ctx),
|
void (*eof_cb)(void *ctx),
|
||||||
void *ctx)
|
void *ctx)
|
||||||
{
|
{
|
||||||
os_memset(history_buf, 0, sizeof(history_buf));
|
dl_list_init(&history_list);
|
||||||
|
history_curr = NULL;
|
||||||
|
|
||||||
edit_cb_ctx = ctx;
|
edit_cb_ctx = ctx;
|
||||||
edit_cmd_cb = cmd_cb;
|
edit_cmd_cb = cmd_cb;
|
||||||
|
@ -1073,6 +1070,11 @@ int edit_init(void (*cmd_cb)(void *ctx, char *cmd),
|
||||||
|
|
||||||
void edit_deinit(void)
|
void edit_deinit(void)
|
||||||
{
|
{
|
||||||
|
struct edit_history *h;
|
||||||
|
while ((h = dl_list_first(&history_list, struct edit_history, list))) {
|
||||||
|
dl_list_del(&h->list);
|
||||||
|
os_free(h);
|
||||||
|
}
|
||||||
eloop_unregister_read_sock(STDIN_FILENO);
|
eloop_unregister_read_sock(STDIN_FILENO);
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &prevt);
|
tcsetattr(STDIN_FILENO, TCSANOW, &prevt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,10 @@ static inline unsigned int dl_list_len(struct dl_list *list)
|
||||||
(dl_list_empty((list)) ? NULL : \
|
(dl_list_empty((list)) ? NULL : \
|
||||||
dl_list_entry((list)->next, type, member))
|
dl_list_entry((list)->next, type, member))
|
||||||
|
|
||||||
|
#define dl_list_last(list, type, member) \
|
||||||
|
(dl_list_empty((list)) ? NULL : \
|
||||||
|
dl_list_entry((list)->prev, type, member))
|
||||||
|
|
||||||
#define dl_list_for_each(item, list, type, member) \
|
#define dl_list_for_each(item, list, type, member) \
|
||||||
for (item = dl_list_entry((list)->next, type, member); \
|
for (item = dl_list_entry((list)->next, type, member); \
|
||||||
&item->member != (list); \
|
&item->member != (list); \
|
||||||
|
@ -86,4 +90,9 @@ static inline unsigned int dl_list_len(struct dl_list *list)
|
||||||
&item->member != (list); \
|
&item->member != (list); \
|
||||||
item = n, n = dl_list_entry(n->member.next, type, member))
|
item = n, n = dl_list_entry(n->member.next, type, member))
|
||||||
|
|
||||||
|
#define dl_list_for_each_reverse(item, list, type, member) \
|
||||||
|
for (item = dl_list_entry((list)->prev, type, member); \
|
||||||
|
&item->member != (list); \
|
||||||
|
item = dl_list_entry(item->member.prev, type, member))
|
||||||
|
|
||||||
#endif /* LIST_H */
|
#endif /* LIST_H */
|
||||||
|
|
Loading…
Reference in a new issue