diff --git a/src/msh.c b/src/msh.c index e9a4bb1..0970b3b 100644 --- a/src/msh.c +++ b/src/msh.c @@ -153,6 +153,8 @@ int main(int argc, char** argv) { char** history = NULL; size_t historycapacity = 0; size_t historyi = 0; + size_t historyoffset = 0; + char* oldline = NULL; int pid; @@ -324,6 +326,8 @@ int main(int argc, char** argv) { memset(line, 0, linecapacity); + historyoffset = 0; + while ((readc = getchar()) != '\n') { if (readc == EOF) { printf("^D\n"); @@ -341,6 +345,56 @@ int main(int argc, char** argv) { if (cursor < linelen) { 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) { if (cursor > 0) { 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"); cursor = index; } - - goto print_prompt; - } - - // backspace - if (readc == 127) { + } else if (readc == 127) { + // backspace if (cursor > 0) { cursor--; linelen--; @@ -371,33 +421,30 @@ int main(int argc, char** argv) { } else { memmove(line + cursor, line + cursor + 1, LINESIZE - (cursor)); } - - // We don't want to change the line - goto print_prompt; - } - - if (cursor != linelen) { - memmove(line + cursor + 1, line + cursor, LINESIZE - cursor - 1); - } - - line[cursor] = readc; - cursor++; - linelen++; - - // Are we out of capacity? Double line length - while (linelen >= linecapacity - 1) { - linecapacity *= 2; - line = realloc(line, linecapacity); - if (line == NULL) { - fprintf(stderr, "Error: Failed to re-allocated line buffer"); - retval = 1; - goto cleanup; + } else { + // We are typing + if (cursor != linelen) { + memmove(line + cursor + 1, line + cursor, LINESIZE - cursor - 1); } - memset(line + linecapacity / 2, 0, linecapacity / 2); + line[cursor] = readc; + cursor++; + linelen++; + + // Are we out of capacity? Double line length + while (linelen >= linecapacity - 1) { + linecapacity *= 2; + line = realloc(line, linecapacity); + if (line == NULL) { + fprintf(stderr, "Error: Failed to re-allocated line buffer"); + retval = 1; + goto cleanup; + } + + memset(line + linecapacity / 2, 0, linecapacity / 2); + } } -print_prompt: // Manual echo printf(ANSI_ESC "[2K" ANSI_ESC "[0G" "%s%s", prompt, line); for (int j = 0; j < linelen - cursor; j++) { @@ -530,6 +577,10 @@ cleanup: free(line); } + if (oldline != NULL) { + free(oldline); + } + if (tokenwork != NULL) { free(tokenwork); }