#include "../src/nasal.h" #include "../src/nasal_type.h" #include "../src/nasal_gc.h" #include <iostream> #ifndef _MSC_VER #include <unistd.h> #endif #ifdef _MSC_VER #pragma warning (disable:4996) #endif #ifdef _WIN32 #include <conio.h> #else #include <fcntl.h> #include <termios.h> #endif namespace nasal { class noecho_input { private: #ifndef _WIN32 struct termios init_termios; struct termios new_termios; int peek_char = -1; #endif public: noecho_input() { #ifndef _WIN32 tcflush(0, TCIOFLUSH); tcgetattr(0, &init_termios); new_termios = init_termios; new_termios.c_lflag &= ~(ICANON|ECHO|ECHONL|ECHOE); // vmin = 0 is nonblock input, // but in wsl1 there is a bug that will block input // so we use fcntl to write the nonblock input new_termios.c_cc[VMIN] = 1; new_termios.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, &new_termios); #endif } ~noecho_input() { #ifndef _WIN32 tcflush(0, TCIOFLUSH); tcsetattr(0, TCSANOW, &init_termios); #endif } int noecho_kbhit() { #ifndef _WIN32 unsigned char ch = 0; int nread = 0; if (peek_char!=-1) { return 1; } int flag = fcntl(0, F_GETFL); fcntl(0, F_SETFL, flag|O_NONBLOCK); nread = read(0, &ch, 1); fcntl(0, F_SETFL, flag); if (nread==1) { peek_char = ch; return 1; } return 0; #else return kbhit(); #endif } int noecho_getch() { #ifndef _WIN32 int ch = 0; if (peek_char!=-1) { ch = peek_char; peek_char = -1; return ch; } ssize_t tmp = read(0, &ch, 1); return ch; #else return getch(); #endif } }; noecho_input this_window; var nas_getch(var* args, usize size, gc* ngc) { return var::num(static_cast<double>(this_window.noecho_getch())); } var nas_kbhit(var* args, usize size, gc* ngc) { return var::num(static_cast<double>(this_window.noecho_kbhit())); } var nas_noblock(var* args, usize size, gc* ngc) { if (this_window.noecho_kbhit()) { return var::num(static_cast<double>(this_window.noecho_getch())); } return nil; } module_func_info func_tbl[] = { {"nas_getch", nas_getch}, {"nas_kbhit", nas_kbhit}, {"nas_noblock", nas_noblock}, {nullptr, nullptr} }; NASAL_EXTERN module_func_info* get() { return func_tbl; } }