#include #include #include #include #include // https://viewsourcecode.org/snaptoken/kilo/02.enteringRawMode.html struct termios orig_termios; void disableRawMode() { tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios); } void enableRawMode() { tcgetattr(STDIN_FILENO, &orig_termios); atexit(disableRawMode); struct termios raw; tcgetattr(STDIN_FILENO, &raw); raw.c_iflag &= ~(ICRNL | IXON); raw.c_lflag &= ~(ECHO | ICANON | IEXTEN /*| ISIG*/); raw.c_cc[VMIN] = 0; raw.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); } char buffer[256]; int move = 0; void refreshLine() { putchar('\r'); printf("> %s", buffer); if(move > 0) { printf("\33[%dD", move); } fflush(STDIN_FILENO); } int main() { enableRawMode(); int index = 0; buffer[0] = '\0'; while(1) { int c = 0; int bytes = read(STDIN_FILENO, &c, 1); printf("\33[2K\r"); if(bytes < 0) { break; } else if(bytes == 0) { //printf("timeout\n"); refreshLine(); continue; } else if(c == 'q') { break; } if(c == 27) { char escape[10]; int escapeBytes = read(STDIN_FILENO, escape, 10); printf("Escape sequence of length: %d\n", escapeBytes); if(escapeBytes == 2) { if(escape[0] == '[' && escape[1] == 'D' && move < index) { move++; } if(escape[0] == '[' && escape[1] == 'C' && move > 0) { move--; } } continue; } if(iscntrl(c)) { switch(c) { case 127: if(index > 0) { if(move == 0) { index--; buffer[index] = '\0'; } else { int pos = index - move - 1; if(pos >= 0) { while(buffer[pos] != '\0') { buffer[pos] = buffer[pos + 1]; pos++; } index--; } } } break; case 13: puts(buffer); index = 0; buffer[0] = '\0'; move = 0; break; } printf("%d\n", c); } else { printf("%d ('%c')\n", c, c); if(move == 0) { buffer[index++] = c; buffer[index] = '\0'; } } refreshLine(); } return 0; }