Add history

This commit is contained in:
Mark
2020-07-13 18:18:42 +03:00
parent 68bd19dca1
commit c5ba7f0da5
4 changed files with 117 additions and 1 deletions
+2 -1
View File
@@ -15,7 +15,8 @@ sh_OBJS=$(O)/sh.o \
$(O)/parse.o \
$(O)/builtin.o \
$(O)/job.o \
$(O)/env.o
$(O)/env.o \
$(O)/history.o
all: mkdirs $(O)/sh
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#define HISTORY_SIZE 128
struct history_entry {
char data[256];
struct history_entry *prev, *next;
};
void history_insert(const char *cmd);
struct history_entry *history_head(void);
+38
View File
@@ -0,0 +1,38 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "history.h"
static struct history_entry *g_history_head, *g_history_tail;
size_t history_size = 0;
struct history_entry *history_head(void) {
return g_history_head;
}
void history_insert(const char *command) {
struct history_entry *ent;
if (history_size == HISTORY_SIZE) {
// Just resuse the last entry
assert(g_history_tail && g_history_tail->prev);
ent = g_history_tail;
g_history_tail = g_history_tail->prev;
g_history_tail->next = NULL;
} else {
ent = malloc(sizeof(struct history_entry));
assert(ent);
}
strcpy(ent->data, command);
ent->prev = NULL;
ent->next = g_history_head;
if (!g_history_tail) {
assert(!g_history_head);
g_history_tail = ent;
} else {
g_history_head->prev = ent;
}
g_history_head = ent;
++history_size;
}
+67
View File
@@ -2,7 +2,9 @@
#include <termios.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <stdio.h>
#include "history.h"
#define KEY_UP (256)
#define KEY_DOWN (257)
@@ -86,6 +88,7 @@ int readline(char *buf, size_t lim) {
int cur = 0;
int chr;
struct history_entry *ent = NULL;
struct termios t0, t1;
tcgetattr(STDIN_FILENO, &t0);
@@ -118,8 +121,65 @@ int readline(char *buf, size_t lim) {
++cur;
}
break;
case KEY_UP:
if (!ent) {
ent = history_head();
} else {
ent = ent->next;
}
if (ent) {
if (cur) {
fprintf(stdout, "\033[%dD", cur);
}
fputs("\033[K", stdout);
fputs(ent->data, stdout);
fflush(stdout);
len = strlen(ent->data);
cur = len;
} else {
if (cur) {
fprintf(stdout, "\033[%dD", cur);
}
fputs("\033[K", stdout);
fflush(stdout);
cur = 0;
len = 0;
}
break;
case KEY_DOWN:
if (ent) {
ent = ent->prev;
if (ent) {
if (cur) {
fprintf(stdout, "\033[%dD", cur);
}
fputs("\033[K", stdout);
fputs(ent->data, stdout);
fflush(stdout);
len = strlen(ent->data);
cur = len;
} else {
if (cur) {
fprintf(stdout, "\033[%dD", cur);
}
fputs("\033[K", stdout);
fflush(stdout);
cur = 0;
len = 0;
}
}
break;
}
if (chr == KEY_UP || chr == KEY_DOWN) {
continue;
}
// Any other move resets history position
ent = NULL;
if (chr == 4) {
if (len == 0) {
fputs("exit\n", stderr);
@@ -162,6 +222,13 @@ int readline(char *buf, size_t lim) {
}
}
const char *e = buf;
while (isspace(*e)) {
++e;
}
if (*e) {
history_insert(buf);
}
tcsetattr(STDIN_FILENO, TCSANOW, &t0);
return len;