Created
August 23, 2023 08:53
-
-
Save schlechter-afk/e4f6df2868ed0ba1d780747535c54d4e to your computer and use it in GitHub Desktop.
terminal_setting
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <termios.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <ctype.h> | |
#include <string.h> | |
void die(const char *s) { | |
perror(s); | |
exit(1); | |
} | |
struct termios orig_termios; | |
void disableRawMode() { | |
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) | |
die("tcsetattr"); | |
} | |
/** | |
* Enable row mode for the terminal | |
* The ECHO feature causes each key you type to be printed to the terminal, so you can see what you’re typing. | |
* Terminal attributes can be read into a termios struct by tcgetattr(). | |
* After modifying them, you can then apply them to the terminal using tcsetattr(). | |
* The TCSAFLUSH argument specifies when to apply the change: in this case, it waits for all pending output to be written to the terminal, and also discards any input that hasn’t been read. | |
* The c_lflag field is for “local flags” | |
*/ | |
void enableRawMode() { | |
if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) die("tcgetattr"); | |
atexit(disableRawMode); | |
struct termios raw = orig_termios; | |
raw.c_lflag &= ~(ICANON | ECHO); | |
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) die("tcsetattr"); | |
} | |
/** | |
* stdout and stdin are buffered we disable buffering on that | |
* After entering in raw mode we read characters one by one | |
* Up arrow keys and down arrow keys are represented by 3 byte escape codes | |
* starting with ascii number 27 i.e. ESC key | |
* This way we interpret arrow keys | |
* Tabs are usually handled by the term, but here we are simulating tabs for the sake of simplicity | |
* Backspace move the cursor one control character to the left | |
* @return | |
*/ | |
int main() { | |
char *inp = malloc(sizeof(char) * 100); | |
char c; | |
while (1) { | |
setbuf(stdout, NULL); | |
enableRawMode(); | |
printf("Prompt>"); | |
memset(inp, '\0', 100); | |
int pt = 0; | |
while (read(STDIN_FILENO, &c, 1) == 1) { | |
if (iscntrl(c)) { | |
if (c == 10) break; | |
else if (c == 27) { | |
char buf[3]; | |
buf[2] = 0; | |
if (read(STDIN_FILENO, buf, 2) == 2) { // length of escape code | |
printf("\rarrow key: %s", buf); | |
} | |
} else if (c == 127) { // backspace | |
if (pt > 0) { | |
if (inp[pt-1] == 9) { | |
for (int i = 0; i < 7; i++) { | |
printf("\b"); | |
} | |
} | |
inp[--pt] = '\0'; | |
printf("\b \b"); | |
} | |
} else if (c == 9) { // TAB character | |
inp[pt++] = c; | |
for (int i = 0; i < 8; i++) { // TABS should be 8 spaces | |
printf(" "); | |
} | |
} else if (c == 4) { | |
exit(0); | |
} else { | |
printf("%d\n", c); | |
} | |
} else { | |
inp[pt++] = c; | |
printf("%c", c); | |
} | |
} | |
disableRawMode(); | |
printf("\nInput Read: [%s]\n", inp); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment