Last active
January 9, 2018 16:32
-
-
Save tyru/1f71fdd2a15fcb4a9dc40f5796394a29 to your computer and use it in GitHub Desktop.
Struggling with ANSI escape code: https://en.wikipedia.org/wiki/ANSI_escape_code
This file contains hidden or 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 <stdlib.h> | |
| #include <stdarg.h> | |
| #include <string.h> | |
| #include <time.h> | |
| #include <ctype.h> | |
| #include <termios.h> | |
| #include <unistd.h> | |
| #define ESC "\x1b" | |
| #define CSI "\x1b\x5b" | |
| #define CSILEN 2 | |
| void out(const char* str) { | |
| printf("%s", str); | |
| fflush(stdout); | |
| } | |
| void outc(const char c) { | |
| printf("%c", c); | |
| fflush(stdout); | |
| } | |
| void outf(const char* fmt, ...) { | |
| va_list arg; | |
| va_start(arg, fmt); | |
| vprintf(fmt, arg); | |
| va_end(arg); | |
| fflush(stdout); | |
| } | |
| void escup(int n) { | |
| outf(CSI "%dA", n); | |
| } | |
| void escdown(int n) { | |
| outf(CSI "%dB", n); | |
| } | |
| void escright(int n) { | |
| outf(CSI "%dC", n); | |
| } | |
| void escleft(int n) { | |
| outf(CSI "%dD", n); | |
| } | |
| void escsave() { | |
| out(ESC "7"); | |
| } | |
| void escrestore() { | |
| out(ESC "8"); | |
| } | |
| size_t read_until(char *p, size_t size, int in_fd, char end) { | |
| size_t i = 0; | |
| char buf[1] = {0}; | |
| while (i + 1 < size) { | |
| switch (read(in_fd, buf, 1)) { | |
| case -1: // TODO: handle error | |
| case 0: | |
| goto end; | |
| } | |
| p[i] = buf[0]; | |
| i++; | |
| if (buf[0] == end) { | |
| break; | |
| } | |
| } | |
| end: | |
| p[i] = '\0'; | |
| return i + 1; | |
| } | |
| void sleep_msec(long msec) { | |
| struct timespec ts; | |
| ts.tv_sec = msec / 1000; | |
| ts.tv_nsec = (msec % 1000) * 1000 * 1000; | |
| nanosleep(&ts, NULL); | |
| } | |
| void get_cursor(int* x, int* y) { | |
| *x = *y = 0; | |
| outf(CSI "6n"); | |
| char buf[32] = {0}; | |
| read_until(buf, sizeof(buf), STDIN_FILENO, 'R'); | |
| char *p = buf; | |
| p += CSILEN; | |
| while (*p != ';') { | |
| if (!isdigit(*p)) { | |
| goto error; | |
| } | |
| *x = *x * 10 + (*p - '0'); | |
| p++; | |
| } | |
| p++; | |
| while (*p != 'R') { | |
| if (!isdigit(*p)) { | |
| goto error; | |
| } | |
| *y = *y * 10 + (*p - '0'); | |
| p++; | |
| } | |
| return; | |
| error: | |
| *x = *y = -1; | |
| } | |
| void demo_bars() { | |
| const int line = 3; | |
| for (int width = 1; width <= 80; width++) { | |
| escsave(); | |
| for (int i = 0; i < line; i++) { | |
| if (width > 1) { | |
| escright(width - 1); | |
| } | |
| out("*\n"); | |
| } | |
| escrestore(); | |
| sleep_msec(30); | |
| } | |
| escdown(line); | |
| } | |
| void demo_get_cursor() { | |
| // https://stackoverflow.com/a/8101262/6321251 | |
| struct termios ttystate, ttysave; | |
| tcgetattr(STDIN_FILENO, &ttystate); | |
| ttysave = ttystate; | |
| ttystate.c_lflag &= ~(ICANON | ECHO); | |
| ttystate.c_cc[VMIN] = 1; | |
| ttystate.c_cc[VTIME] = 0; | |
| tcsetattr(STDIN_FILENO, TCSANOW, &ttystate); | |
| out("あえいうえおあお"); | |
| int x, y; | |
| get_cursor(&x, &y); | |
| tcsetattr(STDIN_FILENO, TCSANOW, &ttysave); | |
| // y should be 17 | |
| outf("(%d, %d)\n", x, y); | |
| } | |
| int main(int argc, char const* argv[]) | |
| { | |
| // demo_bars(); | |
| demo_get_cursor(); | |
| return 0; | |
| } |
Author
Author
read(2) blocks even when non-canonical mode (min=1) on Vim's :terminal. it seems bug maybe vim-jp/issues#1140
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Memo