77
88#include " GEngine/libdev/systems/CLI.hpp"
99
10+ #include " GEngine/net/events/socket_event.hpp"
11+ #include " GEngine/net/net_socket_system.hpp"
12+ #include " GEngine/net/net_wait.hpp"
13+
1014namespace gengine ::system {
15+
1116CLI::CLI ()
1217 : m_stopReading(false ) {
1318}
@@ -19,32 +24,94 @@ void CLI::init(void) {
1924}
2025
2126void CLI::onStartEngine (gengine::system::event::StartEngine &e [[maybe_unused]]) {
27+ m_socketSTD.setStd (STD_IN);
28+ #ifndef NET_USE_HANDLE
29+ m_wait.addSocketPool (m_socketSTD);
30+ m_wait.addSocketPool (m_socketEventStop);
31+ #endif
2232 m_inputThread = std::thread (&CLI::getInputs, this );
23- m_inputThread.detach ();
2433}
2534
2635void CLI::onStopEngine (gengine::system::event::StopEngine &e [[maybe_unused]]) {
2736 m_stopReading = true ;
37+
38+ m_socketEventStop.signal ();
39+
40+ #ifdef NET_USE_HANDLE
41+ SetConsoleMode (m_socketSTD.getHandle (), m_dwMod);
42+ #endif
43+
44+ if (m_inputThread.joinable ())
45+ m_inputThread.join ();
2846}
2947
3048void CLI::onMainLoop (gengine::system::event::MainLoop &e [[maybe_unused]]) {
3149 std::lock_guard<std::mutex> lock (m_historyMutex);
50+ if (m_stopProgram) {
51+ publishEvent (gengine::system::event::StopMainLoop ());
52+ return ;
53+ }
54+
3255 for (const auto &entry : m_userInputHistory)
3356 publishEvent (gengine::system::event::CLINewInput (splitInput (entry)));
3457 m_userInputHistory.clear ();
3558}
3659
37- void CLI::getInputs (void ) {
60+ void CLI::processOutput (void ) {
3861 std::string input;
3962
63+ auto &res = std::getline (std::cin, input);
64+ if (res.eof ()) {
65+ m_stopProgram = true ;
66+ m_stopReading = true ;
67+ return ;
68+ }
69+
70+ if (!input.empty ()) {
71+ std::lock_guard<std::mutex> lock (m_historyMutex);
72+ m_userInputHistory.push_back (input);
73+ }
74+
75+ /* ugly way of output a > once it's printed */
76+ std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
77+ }
78+
79+ void CLI::getInputs (void ) {
80+ #ifdef NET_USE_HANDLE
81+ GetConsoleMode (m_socketSTD.getHandle (), &m_dwMod);
82+
83+ DWORD fdwMode = m_dwMod & ~(ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
84+ SetConsoleMode (m_socketSTD.getHandle (), fdwMode);
85+
86+ /* flush to remove existing events */
87+ FlushConsoleInputBuffer (m_socketSTD.getHandle ());
88+ #endif
4089 while (!m_stopReading) {
90+ Network::NetWaitSet set;
91+
92+ set.setAlert (m_socketEventStop, [this ]() {
93+ /* do nothing, just loopback since the thread must be killed */
94+ return true ;
95+ });
96+
97+ set.setAlert (m_socketSTD, [this ]() {
98+ processOutput ();
99+ return true ;
100+ });
101+
41102 std::cout << " > " << std::flush;
42- if (std::getline (std::cin, input)) {
43- std::lock_guard<std::mutex> lock (m_historyMutex);
44- m_userInputHistory.push_back (input);
45- } else
103+ bool hasActivity = m_wait.wait (1000000000 , set);
104+ if (!hasActivity)
105+ continue ;
106+
107+ #ifdef NET_USE_HANDLE
108+ set.applyCallback (false );
109+ #else
110+ if (set.isSignaled (m_socketEventStop)) /* */
46111 break ;
47- std::this_thread::sleep_for (std::chrono::milliseconds (100 ));
112+ if (set.isSignaled (m_socketSTD))
113+ processOutput ();
114+ #endif
48115 }
49116}
50117
0 commit comments