TrinityCore
CliRunnable.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
21
22#include "CliRunnable.h"
23#include "Config.h"
24#include "Util.h"
25#include "World.h"
26
27#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
28#include "Chat.h"
29#include "ChatCommand.h"
30#include <readline/readline.h>
31#include <readline/history.h>
32#else
33#include <Windows.h>
34#endif
35
36static constexpr char CLI_PREFIX[] = "TC> ";
37
38static inline void PrintCliPrefix()
39{
40 printf("%s", CLI_PREFIX);
41}
42
43#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
44namespace Trinity::Impl::Readline
45{
46 static std::vector<std::string> vec;
47 char* cli_unpack_vector(char const*, int state)
48 {
49 static size_t i=0;
50 if (!state)
51 i = 0;
52 if (i < vec.size())
53 return strdup(vec[i++].c_str());
54 else
55 return nullptr;
56 }
57
58 char** cli_completion(char const* text, int /*start*/, int /*end*/)
59 {
60 ::rl_attempted_completion_over = 1;
61 vec = Trinity::ChatCommands::GetAutoCompletionsFor(CliHandler(nullptr,nullptr), text);
62 return ::rl_completion_matches(text, &cli_unpack_vector);
63 }
64
65 int cli_hook_func()
66 {
67 if (World::IsStopped())
68 ::rl_done = 1;
69 return 0;
70 }
71}
72#endif
73
74void utf8print(void* /*arg*/, std::string_view str)
75{
76#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
77 WriteWinConsole(str);
78#else
79{
81 fflush(stdout);
82}
83#endif
84}
85
86void commandFinished(void*, bool /*success*/)
87{
89 fflush(stdout);
90}
91
92#ifdef linux
93// Non-blocking keypress detector, when return pressed, return 1, else always return 0
94int kb_hit_return()
95{
96 struct timeval tv;
97 fd_set fds;
98 tv.tv_sec = 0;
99 tv.tv_usec = 0;
100 FD_ZERO(&fds);
101 FD_SET(STDIN_FILENO, &fds);
102 select(STDIN_FILENO+1, &fds, nullptr, nullptr, &tv);
103 return FD_ISSET(STDIN_FILENO, &fds);
104}
105#endif
106
109{
110#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
111 // print this here the first time
112 // later it will be printed after command queue updates
114#else
115 ::rl_attempted_completion_function = &Trinity::Impl::Readline::cli_completion;
116 {
117 static char BLANK = '\0';
118 ::rl_completer_word_break_characters = &BLANK;
119 }
120 ::rl_event_hook = &Trinity::Impl::Readline::cli_hook_func;
121#endif
122
123 if (sConfigMgr->GetBoolDefault("BeepAtStart", true))
124 printf("\a"); // \a = Alert
125
126#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
127 if (sConfigMgr->GetBoolDefault("FlashAtStart", true))
128 {
129 FLASHWINFO fInfo;
130 fInfo.cbSize = sizeof(FLASHWINFO);
131 fInfo.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
132 fInfo.hwnd = GetConsoleWindow();
133 fInfo.uCount = 0;
134 fInfo.dwTimeout = 0;
135 FlashWindowEx(&fInfo);
136 }
137#endif
139 while (!World::IsStopped())
140 {
141 fflush(stdout);
142
143 std::string command;
144
145#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
146 if (!ReadWinConsole(command))
147 continue;
148#else
149 char* command_str = readline(CLI_PREFIX);
150 ::rl_bind_key('\t', ::rl_complete);
151 if (command_str != nullptr)
152 {
153 command = command_str;
154 free(command_str);
155 }
156#endif
157
158 if (!command.empty())
159 {
160 Optional<std::size_t> nextLineIndex = RemoveCRLF(command);
161 if (nextLineIndex && *nextLineIndex == 0)
162 {
163#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
165#endif
166 continue;
167 }
168
169 fflush(stdout);
170 sWorld->QueueCliCommand(new CliCommandHolder(nullptr, command.c_str(), &utf8print, &commandFinished));
171#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
172 add_history(command.c_str());
173#endif
174 }
175 else if (feof(stdin))
176 {
178 }
179 }
180}
#define sConfigMgr
Definition: Config.h:61
#define STRING_VIEW_FMT_ARG(str)
Definition: Define.h:135
#define STRING_VIEW_FMT
Definition: Define.h:134
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
bool WriteWinConsole(std::string_view str, bool error)
Definition: Util.cpp:826
TC_COMMON_API Optional< std::size_t > RemoveCRLF(std::string &str)
Definition: Util.cpp:839
bool ReadWinConsole(std::string &str, size_t size)
Definition: Util.cpp:807
static void StopNow(uint8 exitcode)
Definition: World.h:670
static bool IsStopped()
Definition: World.h:671
void CliThread()
Thread start
static void PrintCliPrefix()
Definition: CliRunnable.cpp:38
static constexpr char CLI_PREFIX[]
Definition: CliRunnable.cpp:36
void utf8print(void *, std::string_view str)
Definition: CliRunnable.cpp:74
void commandFinished(void *, bool)
Definition: CliRunnable.cpp:86
#define sWorld
Definition: World.h:931
@ SHUTDOWN_EXIT_CODE
Definition: World.h:74
TC_GAME_API std::vector< std::string > GetAutoCompletionsFor(ChatHandler const &handler, std::string_view cmd)
Storage class for commands issued for delayed execution.
Definition: World.h:542