/// /// Created by Anonymous275 on 10/29/2020 /// #include "Lua/LuaSystem.hpp" #ifdef WIN32 #include #include #else // *nix typedef unsigned long DWORD, *PDWORD, *LPDWORD; #include #include #endif // WIN32 #include "Logger.h" #include #include #include #include std::vector QConsoleOut; std::string CInputBuff; std::mutex MLock; std::unique_ptr LuaConsole; void HandleInput(const std::string& cmd) { std::cout << std::endl; if (cmd == "exit") { exit(0); } else LuaConsole->Execute(cmd); } void ProcessOut() { static size_t len = 2; if (QConsoleOut.empty() && len == CInputBuff.length()) return; printf("%c[2K\r", 27); for (const std::string& msg : QConsoleOut) if (!msg.empty()) std::cout << msg; MLock.lock(); QConsoleOut.clear(); MLock.unlock(); std::cout << "> " << CInputBuff << std::flush; len = CInputBuff.length(); } void ConsoleOut(const std::string& msg) { MLock.lock(); QConsoleOut.emplace_back(msg); MLock.unlock(); } [[noreturn]] void OutputRefresh() { DebugPrintTID(); while (true) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); ProcessOut(); } } #ifndef WIN32 static int _getch() { char buf = 0; struct termios old; fflush(stdout); if (tcgetattr(0, &old) < 0) perror("tcsetattr()"); old.c_lflag &= ~unsigned(ICANON); old.c_lflag &= ~unsigned(ECHO); old.c_cc[VMIN] = 1; old.c_cc[VTIME] = 0; if (tcsetattr(0, TCSANOW, &old) < 0) perror("tcsetattr ICANON"); if (read(0, &buf, 1) < 0) perror("read()"); old.c_lflag |= ICANON; old.c_lflag |= ECHO; if (tcsetattr(0, TCSADRAIN, &old) < 0) perror("tcsetattr ~ICANON"); // no echo printf("%c\n", buf); return buf; } #endif // WIN32 void SetupConsole() { #ifdef WIN32 DWORD outMode = 0; HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); if (stdoutHandle == INVALID_HANDLE_VALUE) { error("Invalid handle"); std::this_thread::sleep_for(std::chrono::seconds(3)); exit(GetLastError()); } if (!GetConsoleMode(stdoutHandle, &outMode)) { error("Invalid console mode"); std::this_thread::sleep_for(std::chrono::seconds(3)); exit(GetLastError()); } // Enable ANSI escape codes outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; if (!SetConsoleMode(stdoutHandle, outMode)) { error("failed to set console mode"); std::this_thread::sleep_for(std::chrono::seconds(3)); exit(GetLastError()); } #else #endif // WIN32 } [[noreturn]] void ReadCin() { DebugPrintTID(); while (true) { int In = _getch(); if (In == 13 || In == '\n') { if (!CInputBuff.empty()) { HandleInput(CInputBuff); CInputBuff.clear(); } } else if (In == 8) { if (!CInputBuff.empty()) CInputBuff.pop_back(); } else if (In == 4) { CInputBuff = "exit"; HandleInput(CInputBuff); CInputBuff.clear(); } else { CInputBuff += char(In); } } } void ConsoleInit() { SetupConsole(); LuaConsole = std::make_unique(true); printf("> "); std::thread In(ReadCin); In.detach(); std::thread Out(OutputRefresh); Out.detach(); }