#include #include #include #include #include void move_cursor(int direction, uint8_t *pos, int len) { if (direction == -1) { if (*pos != 0) { *pos -= 1; } else { return; } printf("\x0D "); printf("\x0D\x1B[1A>"); printf("\x0D"); } else if (direction == 1) { if (*pos != len - 1) { *pos += 1; } else { return; } printf("\x0D "); printf("\x0D\x1B[1B>"); printf("\x0D"); } fflush(stdout); } struct termios setup_term() { struct termios old, new; tcgetattr(STDIN_FILENO, &old); new = old; new.c_lflag &= ~(ECHO | ICANON); new.c_cc[VMIN] = 0; // bytes read to return new.c_cc[VTIME] = 0; // time before return tcsetattr(STDIN_FILENO, TCSANOW, &new); return old; } void return_term(struct termios *old) { tcsetattr(STDIN_FILENO, TCSANOW, old); } int menu(char **elements, int len) { struct pollfd poller[1]; poller[0].fd = STDIN_FILENO; poller[0].events = POLLIN; for (int i = 0; i < len; i++) { printf(" %s\n", elements[i]); } printf("\x1B[%dA>\x0D", len); fflush(stdout); uint8_t pos = 0; while (1) { int events = poll(poller, 1, -1); if (events > 0 && poller[0].revents & POLLIN) { char buffer[10]; uint16_t length = read(STDIN_FILENO, buffer, sizeof(buffer)); if (length > 0) { uint8_t i; for (i = 0; i < length; i++) { if (buffer[i] == 'q') return -1; else if (buffer[i] == 'j') { move_cursor(1, &pos, len); } else if (buffer[i] == 'k') { move_cursor(-1, &pos, len); } else if (buffer[i] == 'o') { return pos; } } } else { return -1; } } else { return -1; } } } int main() { struct termios old = setup_term(); static char *elements[] = {"hi", "hello", "what's up"}; int seli = menu(elements, 3); if (seli < 0) { printf("ERROR: menu failed"); return 1; } return_term(&old); printf("%s", elements[seli]); return 0; }