feat: history browsing with arrow keys

This commit is contained in:
2026-10-10 01:44:12 +02:00
parent a1df9fca4f
commit 0794ed12ed

View File

@@ -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);
} }