MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

clean up readline module

+122 -159
+122 -159
src/modules/readline.c
··· 99 99 #ifndef _WIN32 100 100 struct termios saved_termios; 101 101 bool raw_mode; 102 + uv_signal_t sigint_watcher; 103 + bool sigint_watcher_active; 102 104 #endif 103 105 } rl_interface_t; 104 106 ··· 232 234 if (tcgetattr(STDIN_FILENO, &iface->saved_termios) == -1) return; 233 235 234 236 raw = iface->saved_termios; 235 - raw.c_lflag &= ~(ICANON | ECHO | ISIG); 236 - raw.c_cc[VMIN] = 1; 237 - raw.c_cc[VTIME] = 0; 238 - 237 + cfmakeraw(&raw); 238 + raw.c_lflag |= ISIG; 239 + 239 240 if (tcsetattr(STDIN_FILENO, TCSANOW, &raw) == -1) return; 240 241 iface->raw_mode = true; 241 242 } ··· 445 446 } 446 447 447 448 static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) { 448 - (void)handle; 449 449 buf->base = malloc(suggested_size); 450 450 buf->len = suggested_size; 451 451 } 452 452 453 - static void on_stdin_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { 454 - rl_interface_t *iface = (rl_interface_t *)stream->data; 455 - ant_t *js = rt->js; 456 - 457 - if (!iface) { 458 - if (buf->base) free(buf->base); 459 - return; 460 - } 461 - 462 - if (iface->closed || iface->paused) { 463 - if (buf->base) free(buf->base); 464 - return; 465 - } 466 - 467 - if (nread < 0) { 468 - if (nread == UV_EOF) { 469 - emit_event(js, iface, "close", NULL, 0); 470 - iface->closed = true; 471 - } 472 - if (buf->base) free(buf->base); 473 - return; 474 - } 475 - 476 - for (ssize_t i = 0; i < nread; i++) { 477 - char c = buf->base[i]; 478 - 479 - if (iface->escape_state > 0) { 480 - iface->escape_buf[iface->escape_len++] = c; 481 - 482 - if (iface->escape_state == 1) { 483 - if (c == '[' || c == 'O') { 484 - iface->escape_state = 2; 485 - } else { 486 - iface->escape_state = 0; 487 - iface->escape_len = 0; 488 - } 489 - } else if (iface->escape_state == 2) { 490 - if ((c >= 'A' && c <= 'Z') || c == '~') { 491 - handle_escape_sequence(iface, iface->escape_buf, iface->escape_len); 492 - iface->escape_state = 0; 493 - iface->escape_len = 0; 494 - } else if (iface->escape_len >= 15) { 495 - iface->escape_state = 0; 496 - iface->escape_len = 0; 497 - } 498 - } 499 - continue; 500 - } 501 - 502 - if (c == 27) { 503 - iface->escape_state = 1; 504 - iface->escape_len = 0; 505 - continue; 506 - } 507 - 508 - if (c == '\r' || c == '\n') { 509 - printf("\n"); 510 - fflush(stdout); 511 - 512 - char *line = strdup(iface->line_buffer); 513 - rl_history_add(&iface->history, line, iface->remove_history_duplicates); 514 - emit_history_event(js, iface); 515 - 516 - ant_value_t line_val = js_mkstr(js, line, strlen(line)); 517 - emit_event(js, iface, "line", &line_val, 1); 518 - 519 - if (vtype(iface->pending_question_resolve) == T_FUNC) { 520 - sv_vm_call(js->vm, js, iface->pending_question_resolve, js_mkundef(), &line_val, 1, NULL, false); 521 - iface->pending_question_resolve = js_mkundef(); 522 - iface->pending_question_reject = js_mkundef(); 523 - } 524 - 525 - iface->line_buffer[0] = '\0'; 526 - iface->line_pos = 0; 527 - iface->line_len = 0; 528 - iface->history.current = iface->history.count; 529 - 530 - free(line); 531 - } else if (c == 127 || c == 8) { 532 - handle_backspace(iface); 533 - } else if (c == 3) { 534 - if (rl_has_event_listener(iface, "SIGINT")) { 535 - emit_event(js, iface, "SIGINT", NULL, 0); 536 - } else if (process_has_event_listeners("SIGINT")) { 537 - ant_value_t sig_arg = js_mkstr(js, "SIGINT", 6); 538 - emit_process_event("SIGINT", &sig_arg, 1); 539 - } else { 540 - uv_tty_reset_mode(); 541 - raise(SIGINT); 542 - } 543 - } else if (c == 4) { 544 - if (iface->line_len == 0) { 545 - emit_event(js, iface, "close", NULL, 0); 546 - iface->closed = true; 547 - uv_read_stop(stream); 548 - } else handle_delete(iface); 549 - } else if (c == 1) { 550 - iface->line_pos = 0; 551 - refresh_line(iface); 552 - } else if (c == 5) { 553 - iface->line_pos = iface->line_len; 554 - refresh_line(iface); 555 - } else if (c == 11) { 556 - iface->line_buffer[iface->line_pos] = '\0'; 557 - iface->line_len = iface->line_pos; 558 - refresh_line(iface); 559 - } else if (c == 21) { 560 - iface->line_buffer[0] = '\0'; 561 - iface->line_pos = 0; 562 - iface->line_len = 0; 563 - refresh_line(iface); 564 - } else if (c == 12) { 565 - printf("\033[2J\033[H"); 566 - refresh_line(iface); 567 - } else if (c >= 32 && c < 127) { 568 - handle_char_input(iface, c); 569 - } 570 - } 571 - 572 - if (buf->base) free(buf->base); 573 - } 574 - 575 - static void start_reading(rl_interface_t *iface) { 576 - if (iface->reading || iface->closed) return; 577 - 578 - if (!iface->tty_initialized) { 579 - uv_loop_t *loop = uv_default_loop(); 580 - int is_tty = uv_guess_handle(STDIN_FILENO) == UV_TTY; 581 - 582 - if (is_tty) { 583 - if (uv_tty_init(loop, &iface->tty_in, STDIN_FILENO, 1) != 0) return; 584 - uv_tty_set_mode(&iface->tty_in, UV_TTY_MODE_RAW); 585 - } else { 586 - if (uv_tty_init(loop, &iface->tty_in, STDIN_FILENO, 1) != 0) return; 587 - } 588 - 589 - iface->tty_in.data = iface; 590 - iface->tty_initialized = true; 591 - } 592 - 593 - iface->reading = true; 594 - uv_read_start((uv_stream_t *)&iface->tty_in, alloc_buffer, on_stdin_read); 595 - } 596 - 597 453 static void stop_reading(rl_interface_t *iface) { 598 454 if (!iface->reading) return; 599 - 455 + 600 456 uv_read_stop((uv_stream_t *)&iface->tty_in); 601 457 iface->reading = false; 458 + #ifndef _WIN32 459 + if (iface->sigint_watcher_active) { 460 + uv_signal_stop(&iface->sigint_watcher); 461 + iface->sigint_watcher_active = false; 462 + } 463 + #endif 602 464 } 603 465 604 466 static void process_line(ant_t *js, rl_interface_t *iface) { ··· 623 485 free(line); 624 486 } 625 487 488 + static void feed_escape(rl_interface_t *iface, char c) { 489 + iface->escape_buf[iface->escape_len++] = c; 490 + if (iface->escape_state == 1) { 491 + iface->escape_state = (c == '[' || c == 'O') ? 2 : 0; 492 + if (!iface->escape_state) iface->escape_len = 0; 493 + return; 494 + } 495 + bool done = (c >= 'A' && c <= 'Z') || c == '~'; 496 + if (done) handle_escape_sequence(iface, iface->escape_buf, iface->escape_len); 497 + if (done || iface->escape_len >= 15) { iface->escape_state = 0; iface->escape_len = 0; } 498 + } 499 + 500 + static void process_byte(ant_t *js, rl_interface_t *iface, char c) { 501 + if (iface->escape_state > 0) { feed_escape(iface, c); return; } 502 + if (c == 27) { iface->escape_state = 1; iface->escape_len = 0; return; } 503 + 504 + switch (c) { 505 + case '\r': case '\n': 506 + putchar('\n'); fflush(stdout); 507 + process_line(js, iface); 508 + break; 509 + case 127: case 8: handle_backspace(iface); break; 510 + case 4: 511 + if (iface->line_len == 0) { emit_event(js, iface, "close", NULL, 0); iface->closed = true; } 512 + else handle_delete(iface); 513 + break; 514 + case 1: iface->line_pos = 0; refresh_line(iface); break; 515 + case 5: iface->line_pos = iface->line_len; refresh_line(iface); break; 516 + case 11: iface->line_buffer[iface->line_pos] = '\0'; iface->line_len = iface->line_pos; refresh_line(iface); break; 517 + case 21: iface->line_buffer[0] = '\0'; iface->line_pos = 0; iface->line_len = 0; refresh_line(iface); break; 518 + case 12: printf("\033[2J\033[H"); refresh_line(iface); break; 519 + default: if (c >= 32 && c < 127) handle_char_input(iface, c); break; 520 + } 521 + } 522 + 523 + static void on_stdin_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) { 524 + rl_interface_t *iface = (rl_interface_t *)stream->data; 525 + ant_t *js = rt->js; 526 + 527 + if (!iface || iface->closed || iface->paused) goto cleanup; 528 + 529 + if (nread < 0) { 530 + if (nread == UV_EOF) { emit_event(js, iface, "close", NULL, 0); iface->closed = true; } 531 + goto cleanup; 532 + } 533 + 534 + for (ssize_t i = 0; i < nread; i++) { 535 + process_byte(js, iface, buf->base[i]); 536 + if (iface->closed) break; 537 + } 538 + 539 + if (iface->closed) stop_reading(iface); 540 + 541 + cleanup: 542 + free(buf->base); 543 + } 544 + 545 + #ifndef _WIN32 546 + static void on_sigint(uv_signal_t *handle, int signum) { 547 + rl_interface_t *iface = (rl_interface_t *)handle->data; 548 + ant_t *js = rt->js; 549 + 550 + if (rl_has_event_listener(iface, "SIGINT")) { 551 + emit_event(js, iface, "SIGINT", NULL, 0); 552 + } else if (process_has_event_listeners("SIGINT")) { 553 + ant_value_t sig_arg = js_mkstr(js, "SIGINT", 6); 554 + emit_process_event("SIGINT", &sig_arg, 1); 555 + } else { 556 + uv_signal_stop(handle); 557 + raise(SIGINT); 558 + } 559 + } 560 + #endif 561 + 562 + static void start_reading(rl_interface_t *iface) { 563 + if (iface->reading || iface->closed) return; 564 + 565 + if (!iface->tty_initialized) { 566 + uv_loop_t *loop = uv_default_loop(); 567 + int is_tty = uv_guess_handle(STDIN_FILENO) == UV_TTY; 568 + 569 + if (uv_tty_init(loop, &iface->tty_in, STDIN_FILENO, 1) != 0) return; 570 + 571 + if (is_tty) { 572 + #ifndef _WIN32 573 + enter_raw_mode(iface); 574 + uv_signal_init(loop, &iface->sigint_watcher); 575 + iface->sigint_watcher.data = iface; 576 + uv_signal_start(&iface->sigint_watcher, on_sigint, SIGINT); 577 + iface->sigint_watcher_active = true; 578 + #endif 579 + } 580 + 581 + iface->tty_in.data = iface; 582 + iface->tty_initialized = true; 583 + } 584 + 585 + iface->reading = true; 586 + uv_read_start((uv_stream_t *)&iface->tty_in, alloc_buffer, on_stdin_read); 587 + } 588 + 626 589 static rl_interface_t *get_interface(ant_t *js, ant_value_t this_obj) { 627 590 ant_value_t id_val = js_get(js, this_obj, "_rl_id"); 628 591 if (vtype(id_val) != T_NUM) return NULL; ··· 763 726 stop_reading(iface); 764 727 765 728 if (iface->tty_initialized) { 766 - uv_tty_reset_mode(); 767 729 uv_close((uv_handle_t *)&iface->tty_in, NULL); 730 + #ifndef _WIN32 731 + if (!iface->sigint_watcher_active && uv_is_active((uv_handle_t *)&iface->sigint_watcher)) { 732 + uv_close((uv_handle_t *)&iface->sigint_watcher, NULL); 733 + } 734 + exit_raw_mode(iface); 735 + #endif 768 736 iface->tty_initialized = false; 769 737 } 770 - 771 - #ifndef _WIN32 772 - exit_raw_mode(iface); 773 - #endif 774 738 775 739 iface->closed = true; 776 740 emit_event(js, iface, "close", NULL, 0); ··· 1349 1313 mark(js, iface->js_obj); 1350 1314 mark(js, iface->pending_question_resolve); 1351 1315 mark(js, iface->pending_question_reject); 1352 - 1316 + 1353 1317 RLEventType *evt, *evt_tmp; 1354 - HASH_ITER(hh, iface->events, evt, evt_tmp) { 1355 - for (int i = 0; i < evt->listener_count; i++) mark(js, evt->listeners[i].listener); 1356 - } 1318 + HASH_ITER(hh, iface->events, evt, evt_tmp) for (int i = 0; i < evt->listener_count; i++) 1319 + mark(js, evt->listeners[i].listener); 1357 1320 } 1358 1321 }