feat: history browsing with arrow keys
This commit is contained in:
73
src/msh.c
73
src/msh.c
@@ -153,6 +153,8 @@ int main(int argc, char** argv) {
|
|||||||
char** history = NULL;
|
char** history = NULL;
|
||||||
size_t historycapacity = 0;
|
size_t historycapacity = 0;
|
||||||
size_t historyi = 0;
|
size_t historyi = 0;
|
||||||
|
size_t historyoffset = 0;
|
||||||
|
char* oldline = NULL;
|
||||||
|
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
@@ -324,6 +326,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
memset(line, 0, linecapacity);
|
memset(line, 0, linecapacity);
|
||||||
|
|
||||||
|
historyoffset = 0;
|
||||||
|
|
||||||
while ((readc = getchar()) != '\n') {
|
while ((readc = getchar()) != '\n') {
|
||||||
if (readc == EOF) {
|
if (readc == EOF) {
|
||||||
printf("^D\n");
|
printf("^D\n");
|
||||||
@@ -341,6 +345,56 @@ int main(int argc, char** argv) {
|
|||||||
if (cursor < linelen) {
|
if (cursor < linelen) {
|
||||||
cursor++;
|
cursor++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (ansi == ANSI_CURSOR_UP || ansi == ANSI_CURSOR_DOWN) {
|
||||||
|
int changed = 1;
|
||||||
|
|
||||||
|
if (ansi == ANSI_CURSOR_UP && historyoffset < historyi) {
|
||||||
|
historyoffset++;
|
||||||
|
} else if (ansi == ANSI_CURSOR_DOWN && historyoffset > 0) {
|
||||||
|
historyoffset--;
|
||||||
|
|
||||||
|
if (historyoffset == 0) {
|
||||||
|
free(line);
|
||||||
|
line = oldline;
|
||||||
|
linelen = strlen(line);
|
||||||
|
linecapacity = linelen + 1;
|
||||||
|
cursor = linelen;
|
||||||
|
|
||||||
|
oldline = NULL;
|
||||||
|
|
||||||
|
// Don't look up from history
|
||||||
|
changed = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We didn't actually change anything
|
||||||
|
changed = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (changed == 1) {
|
||||||
|
if (oldline != NULL) {
|
||||||
|
free(oldline);
|
||||||
|
}
|
||||||
|
|
||||||
|
oldline = line;
|
||||||
|
char* historyline = history[historyi - (historyoffset)];
|
||||||
|
size_t historylinelen = strlen(historyline);
|
||||||
|
line = malloc(historylinelen + 1);
|
||||||
|
if (line == NULL) {
|
||||||
|
retval = 1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
line = strcpy(line, historyline);
|
||||||
|
if (line == NULL) {
|
||||||
|
retval = 1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = historylinelen;
|
||||||
|
linecapacity = historylinelen + 1;
|
||||||
|
linelen = historylinelen;
|
||||||
|
}
|
||||||
} else if (ansi == ANSI_DELETE_WORD) {
|
} else if (ansi == ANSI_DELETE_WORD) {
|
||||||
if (cursor > 0) {
|
if (cursor > 0) {
|
||||||
size_t index = strnrcspn(line, cursor, " \t");
|
size_t index = strnrcspn(line, cursor, " \t");
|
||||||
@@ -355,12 +409,8 @@ int main(int argc, char** argv) {
|
|||||||
size_t index = strnocspn(line, linelen, cursor, " \t");
|
size_t index = strnocspn(line, linelen, cursor, " \t");
|
||||||
cursor = index;
|
cursor = index;
|
||||||
}
|
}
|
||||||
|
} else if (readc == 127) {
|
||||||
goto print_prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// backspace
|
// backspace
|
||||||
if (readc == 127) {
|
|
||||||
if (cursor > 0) {
|
if (cursor > 0) {
|
||||||
cursor--;
|
cursor--;
|
||||||
linelen--;
|
linelen--;
|
||||||
@@ -371,11 +421,8 @@ int main(int argc, char** argv) {
|
|||||||
} else {
|
} else {
|
||||||
memmove(line + cursor, line + cursor + 1, LINESIZE - (cursor));
|
memmove(line + cursor, line + cursor + 1, LINESIZE - (cursor));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
// We don't want to change the line
|
// We are typing
|
||||||
goto print_prompt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cursor != linelen) {
|
if (cursor != linelen) {
|
||||||
memmove(line + cursor + 1, line + cursor, LINESIZE - cursor - 1);
|
memmove(line + cursor + 1, line + cursor, LINESIZE - cursor - 1);
|
||||||
}
|
}
|
||||||
@@ -396,8 +443,8 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
memset(line + linecapacity / 2, 0, linecapacity / 2);
|
memset(line + linecapacity / 2, 0, linecapacity / 2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
print_prompt:
|
|
||||||
// Manual echo
|
// Manual echo
|
||||||
printf(ANSI_ESC "[2K" ANSI_ESC "[0G" "%s%s", prompt, line);
|
printf(ANSI_ESC "[2K" ANSI_ESC "[0G" "%s%s", prompt, line);
|
||||||
for (int j = 0; j < linelen - cursor; j++) {
|
for (int j = 0; j < linelen - cursor; j++) {
|
||||||
@@ -530,6 +577,10 @@ cleanup:
|
|||||||
free(line);
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldline != NULL) {
|
||||||
|
free(oldline);
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenwork != NULL) {
|
if (tokenwork != NULL) {
|
||||||
free(tokenwork);
|
free(tokenwork);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user